在scrapy中使用phantomJS实现异步爬取的方法


Posted in Python onDecember 17, 2018

使用selenium能够非常方便的获取网页的ajax内容,并且能够模拟用户点击和输入文本等诸多操作,这在使用scrapy爬取网页的过程中非常有用。

网上将selenium集成到scrapy的文章很多,但是很少有能够实现异步爬取的,下面这段代码就重写了scrapy的downloader,同时实现了selenium的集成以及异步。

使用时需要PhantomJSDownloadHandler添加到配置文件的DOWNLOADER中。

# encoding: utf-8
from __future__ import unicode_literals
 
from scrapy import signals
from scrapy.signalmanager import SignalManager
from scrapy.responsetypes import responsetypes
from scrapy.xlib.pydispatch import dispatcher
from selenium import webdriver
from six.moves import queue
from twisted.internet import defer, threads
from twisted.python.failure import Failure
 
 
class PhantomJSDownloadHandler(object):
 
 def __init__(self, settings):
  self.options = settings.get('PHANTOMJS_OPTIONS', {})
 
  max_run = settings.get('PHANTOMJS_MAXRUN', 10)
  self.sem = defer.DeferredSemaphore(max_run)
  self.queue = queue.LifoQueue(max_run)
 
  SignalManager(dispatcher.Any).connect(self._close, signal=signals.spider_closed)
 
 def download_request(self, request, spider):
  """use semaphore to guard a phantomjs pool"""
  return self.sem.run(self._wait_request, request, spider)
 
 def _wait_request(self, request, spider):
  try:
   driver = self.queue.get_nowait()
  except queue.Empty:
   driver = webdriver.PhantomJS(**self.options)
 
  driver.get(request.url)
  # ghostdriver won't response when switch window until page is loaded
  dfd = threads.deferToThread(lambda: driver.switch_to.window(driver.current_window_handle))
  dfd.addCallback(self._response, driver, spider)
  return dfd
 
 def _response(self, _, driver, spider):
  body = driver.execute_script("return document.documentElement.innerHTML")
  if body.startswith("<head></head>"): # cannot access response header in Selenium
   body = driver.execute_script("return document.documentElement.textContent")
  url = driver.current_url
  respcls = responsetypes.from_args(url=url, body=body[:100].encode('utf8'))
  resp = respcls(url=url, body=body, encoding="utf-8")
 
  response_failed = getattr(spider, "response_failed", None)
  if response_failed and callable(response_failed) and response_failed(resp, driver):
   driver.close()
   return defer.fail(Failure())
  else:
   self.queue.put(driver)
   return defer.succeed(resp)
 
 def _close(self):
  while not self.queue.empty():
   driver = self.queue.get_nowait()
   driver.close()

以上这篇在scrapy中使用phantomJS实现异步爬取的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python代码调试的几种方法总结
Apr 15 Python
Python数据结构之翻转链表
Feb 25 Python
用 Python 爬了爬自己的微信朋友(实例讲解)
Aug 25 Python
Python使用正则表达式获取网页中所需要的信息
Jan 29 Python
Python实现合并两个列表的方法分析
May 28 Python
python中将\\uxxxx转换为Unicode字符串的方法
Sep 06 Python
Python基本socket通信控制操作示例
Jan 30 Python
python pandas生成时间列表
Jun 29 Python
Python 利用邮件系统完成远程控制电脑的实现(关机、重启等)
Nov 19 Python
Python简单实现词云图代码及步骤解析
Jun 04 Python
python文件名批量重命名脚本实例代码
Apr 22 Python
Python写情书? 10行代码展示如何把情书写在她的照片里
Apr 21 Python
Python 通过调用接口获取公交信息的实例
Dec 17 #Python
python用插值法绘制平滑曲线
Feb 19 #Python
selenium在执行phantomjs的API并获取执行结果的方法
Dec 17 #Python
Python脚本完成post接口测试的实例
Dec 17 #Python
python:接口间数据传递与调用方法
Dec 17 #Python
python直接获取API传递回来的参数方法
Dec 17 #Python
python获取url的返回信息方法
Dec 17 #Python
You might like
PHP动态创建Web站点的方法
2011/08/14 PHP
php木马webshell扫描器代码
2012/01/25 PHP
thinkphp中连接oracle时封装方法无法用的解决办法
2013/06/17 PHP
php短网址和数字之间相互转换的方法
2015/03/13 PHP
php实现图片上传并利用ImageMagick生成缩略图
2016/03/14 PHP
Yii框架分页实现方法详解
2017/05/20 PHP
ThinkPHP like模糊查询,like多匹配查询,between查询,in查询,一般查询书写方法
2018/09/26 PHP
PHP 实现缩略图
2021/03/09 PHP
JavaScript定义类或函数的几种方式小结
2011/01/09 Javascript
jQuery News Ticker 基于jQuery的即时新闻行情展示插件
2011/11/05 Javascript
div+css+js实现无缝滚动类似marquee无缝滚动兼容firefox
2013/08/29 Javascript
自写的jQuery异步加载数据添加事件
2014/05/15 Javascript
移动端jQuery修正Web页面滑动时div问题的两则实例
2016/05/30 Javascript
iframe中使用jquery进行查找的方法【案例分析】
2016/06/17 Javascript
Javascript OOP之面向对象
2016/07/31 Javascript
jQuery禁用快捷键例如禁用F5刷新 禁用右键菜单等的简单实现
2016/08/31 Javascript
前端开发之CSS原理详解
2017/03/11 Javascript
详解axios在vue中的简单配置与使用
2017/05/10 Javascript
Vue.js自定义事件的表单输入组件方法
2018/03/08 Javascript
详解基于Node.js的HTTP/2 Server实践
2018/05/31 Javascript
详解vue中的父子传值双向绑定及数据更新问题
2019/06/13 Javascript
js实现一个简易计算器
2020/03/30 Javascript
利用JS响应式修改vue实现页面的input值
2019/09/02 Javascript
javascript实现简易计算器功能
2020/09/23 Javascript
python爬取网站数据保存使用的方法
2013/11/20 Python
python中join()方法介绍
2018/10/11 Python
在pytorch中查看可训练参数的例子
2019/08/18 Python
PyCharm专业最新版2019.1安装步骤(含激活码)
2019/10/09 Python
详解Python中namedtuple的使用
2020/04/27 Python
Python实现王者荣耀自动刷金币的完整步骤
2021/01/22 Python
机关党员2014全国两会学习心得体会
2014/03/10 职场文书
罚站检讨书
2015/01/29 职场文书
出纳岗位职责
2015/01/31 职场文书
导游词之珠海轮廓
2019/10/25 职场文书
图解排序算法之希尔排序Java实现
2021/06/26 Java/Android
Mysql binlog日志文件过大的解决
2021/10/05 MySQL