在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中http请求方法库汇总
Jan 06 Python
详解python的数字类型变量与其方法
Nov 20 Python
Flask框架web开发之零基础入门
Dec 10 Python
Python设计模式之解释器模式原理与用法实例分析
Jan 10 Python
详解Django中CBV(Class Base Views)模型源码分析
Feb 25 Python
python实现屏保程序(适用于背单词)
Jul 30 Python
python中dict()的高级用法实现
Nov 13 Python
如何利用pygame实现简单的五子棋游戏
Dec 29 Python
python__new__内置静态方法使用解析
Jan 07 Python
Python importlib模块重载使用方法详解
Oct 13 Python
python实现数学模型(插值、拟合和微分方程)
Nov 13 Python
Python数据模型与Python对象模型的相关总结
Jan 26 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递归调用数组值并用其执行指定函数的方法
2015/04/01 PHP
php compact 通过变量创建数组
2016/11/15 PHP
yii2中LinkPager增加总页数和总记录数的实例
2017/08/28 PHP
JavaScript constructor和instanceof,JSOO中的一对欢喜冤家
2009/05/25 Javascript
javascript动画对象支持加速、减速、缓入、缓出的实现代码
2012/09/30 Javascript
jQuery点击tr实现checkbox选中的方法
2013/03/19 Javascript
jQuery的attr与prop使用介绍
2013/10/10 Javascript
jquery 清空file域示例(兼容个浏览器)
2013/10/11 Javascript
通过pjax实现无刷新翻页(兼容新版jquery)
2014/01/31 Javascript
jQuery的live()方法对hover事件的处理示例
2014/02/27 Javascript
Jquery图片延迟加载插件jquery.lazyload.js的使用方法
2014/05/21 Javascript
jQuery实现鼠标经过提示信息的地图热点效果
2015/04/26 Javascript
js改变Iframe中Src的方法
2015/05/05 Javascript
D3.js实现文本的换行详解
2016/10/14 Javascript
AngularJS ng-repeat指令及Ajax的应用实例分析
2017/07/06 Javascript
vue2.0开发入门笔记之.vue文件的生成和使用
2017/09/19 Javascript
js中document.write和document.writeln的区别
2018/03/11 Javascript
[33:39]DOTA2上海特级锦标赛C组小组赛#2 LGD VS Newbee第二局
2016/02/27 DOTA
python发腾讯微博代码分享
2014/01/10 Python
让python 3支持mysqldb的解决方法
2017/02/14 Python
Python编程实现的简单神经网络算法示例
2018/01/26 Python
python实现接口并发测试脚本
2019/06/25 Python
如何使用Python实现斐波那契数列
2019/07/02 Python
Python多版本开发环境管理工具介绍
2019/07/03 Python
python logging.basicConfig不生效的原因及解决
2020/02/20 Python
学python爬虫能做什么
2020/07/29 Python
基于HTML5 Canvas 实现商场监控实例详解
2017/11/20 HTML / CSS
详解前端HTML5几种存储方式的总结
2016/12/27 HTML / CSS
鞋子女王塔玛拉·梅隆同名奢侈品牌:Tamara Mellon
2017/11/22 全球购物
adidas泰国官网:adidas TH
2020/07/11 全球购物
单位委托书范本
2014/04/04 职场文书
2014年政风行风评议工作总结
2014/10/21 职场文书
三方协议书
2015/01/27 职场文书
领导离职感言
2015/08/03 职场文书
2019数学教师下学期工作总结
2019/06/27 职场文书
PyTorch 如何设置随机数种子使结果可复现
2021/05/12 Python