在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 相关文章推荐
wxpython 学习笔记 第一天
Feb 09 Python
Python的Flask框架中web表单的教程
Apr 20 Python
Python实现程序的单一实例用法分析
Jun 03 Python
Python的装饰器模式与面向切面编程详解
Jun 21 Python
Python开发之快速搭建自动回复微信公众号功能
Apr 22 Python
Python中文分词工具之结巴分词用法实例总结【经典案例】
Apr 15 Python
python验证码识别的示例代码
Sep 21 Python
python实现括号匹配的思路详解
Aug 23 Python
pyqt5 实现工具栏文字图片同时显示
Jun 13 Python
django 中使用DateTime常用的时间查询方式
Dec 03 Python
python利用proxybroker构建爬虫免费IP代理池的实现
Feb 21 Python
python获取对象信息的实例详解
Jul 07 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编程开发“虚拟域名”系统
2006/10/09 PHP
php遍历类中包含的所有元素的方法
2015/05/12 PHP
PHP使用token防止表单重复提交的方法
2016/04/07 PHP
使用一个for循环将N*N的二维数组的所有值置1实现方法
2017/05/29 PHP
PHP实现将base64编码字符串转换成图片示例
2018/06/22 PHP
PHP 对象接口简单实现方法示例
2020/04/13 PHP
使两个iframe的高度与内容自适应,且相等
2006/11/20 Javascript
简单的无缝滚动程序-仅几行代码
2007/05/08 Javascript
解决jquery submit()提交表单提示:f[s] is not a function
2013/01/23 Javascript
Js,alert出现乱码问题的解决方法
2013/06/19 Javascript
深入了解Node.js中的一些特性
2014/09/25 Javascript
IE8下jQuery改变png图片透明度时出现的黑边
2015/08/30 Javascript
javascript正则表达式定义(语法)总结
2016/01/08 Javascript
使用JQuery 加载页面时调用JS的实现方法
2016/05/30 Javascript
用jmSlip编写移动端顶部日历选择控件
2016/10/24 Javascript
javascript跨域请求包装函数与用法示例
2016/11/03 Javascript
jQuery实现手机上输入后隐藏键盘功能
2017/01/04 Javascript
微信小程序实现下拉刷新动画
2019/06/21 Javascript
解决antd 下拉框 input [defaultValue] 的值的问题
2020/10/31 Javascript
[41:52]DOTA2-DPC中国联赛 正赛 CDEC vs Dynasty BO3 第二场 2月22日
2021/03/11 DOTA
Python实现从URL地址提取文件名的方法
2015/05/15 Python
机器学习的框架偏向于Python的13个原因
2017/12/07 Python
pygame游戏之旅 创建游戏窗口界面
2018/11/20 Python
Python3批量生成带logo的二维码方法
2019/06/24 Python
用python给csv里的数据排序的具体代码
2020/07/17 Python
Python爬虫之Selenium实现关闭浏览器
2020/12/04 Python
Python 实现进度条的六种方式
2021/01/06 Python
女子锻炼服装和瑜伽服装:Splits59
2019/03/04 全球购物
Holland & Barrett爱尔兰:英国领先的健康零售商
2019/03/31 全球购物
Envie de Fraise意大利:法国网上推出的孕妇装品牌
2020/10/18 全球购物
外贸业务员求职信范文
2013/12/12 职场文书
优秀求职信范文分享
2014/01/26 职场文书
军训 自我鉴定
2014/02/03 职场文书
高中军训第一天感言
2014/03/06 职场文书
mysql 索引合并的使用
2021/08/30 MySQL
mysql幻读详解实例以及解决办法
2022/06/16 MySQL