在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处理中文编码和判断编码示例
Feb 26 Python
Python常用模块用法分析
Sep 08 Python
Python使用matplotlib简单绘图示例
Feb 01 Python
对numpy中的数组条件筛选功能详解
Jul 02 Python
python版opencv摄像头人脸实时检测方法
Aug 03 Python
Python3内置模块pprint让打印比print更美观详解
Jun 02 Python
python开启debug模式的方法
Jun 27 Python
python Tcp协议发送和接收信息的例子
Jul 22 Python
Python Gitlab Api 使用方法
Aug 28 Python
Django模板语言 Tags使用详解
Sep 09 Python
python实现高斯投影正反算方式
Jan 17 Python
Python图像阈值化处理及算法比对实例解析
Jun 19 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
用libTemplate实现静态网页的生成
2006/10/09 PHP
PHP速成大法
2015/01/30 PHP
nginx 设置多个站跨域
2021/03/09 Servers
FireFox JavaScript全局Event对象
2009/06/14 Javascript
javascript中的array数组使用技巧
2010/01/31 Javascript
Dom 是什么的详细说明
2010/10/25 Javascript
javaScript复制功能调用实现方案
2012/12/13 Javascript
JavaScript获取网页中第一个图片id的方法
2015/04/03 Javascript
JavaScript判断图片是否已经加载完毕的方法汇总
2016/02/05 Javascript
Bootstrap打造一个左侧折叠菜单的系统模板(二)
2016/05/17 Javascript
JavaScript地理位置信息API
2016/06/11 Javascript
原生js获取浏览器窗口及元素宽高常用方法集合
2017/01/18 Javascript
关于vue.js v-bind 的一些理解和思考
2017/06/06 Javascript
js中apply与call简单用法详解
2017/11/06 Javascript
JS实现获取进今年第几天是周几的方法分析
2018/06/27 Javascript
详解微信小程序网络请求接口封装实例
2019/05/02 Javascript
js模拟实现百度搜索
2020/06/28 Javascript
微信小程序实现翻牌抽奖动画
2020/09/21 Javascript
vue+elementUI实现简单日历功能
2020/09/24 Javascript
[58:54]EG vs RNG 2019国际邀请赛小组赛 BO2 第一场 8.16
2019/08/18 DOTA
python实现excel读写数据
2021/03/02 Python
在Django中输出matplotlib生成的图片方法
2018/05/24 Python
python flask web服务实现更换默认端口和IP的方法
2019/07/26 Python
Python Django模板之模板过滤器与自定义模板过滤器示例
2019/10/18 Python
python实现计算器功能
2019/10/31 Python
python不相等的两个字符串的 if 条件判断为True详解
2020/03/12 Python
Python Pivot table透视表使用方法解析
2020/09/11 Python
Python读写锁实现实现代码解析
2020/11/28 Python
python中封包建立过程实例
2021/02/18 Python
pycharm Tab键设置成4个空格的操作
2021/02/26 Python
为有想象力的人提供的生活方式商店:Firebox
2018/06/04 全球购物
心碎乌托邦的创业计划书范文
2013/12/26 职场文书
数学复习课教学反思
2016/02/18 职场文书
Android Flutter实现图片滑动切换效果
2022/04/07 Java/Android
Python查找算法的实现 (线性、二分,分块、插值查找算法)
2022/04/24 Python
Apache Kafka 分区重分配的实现原理解析
2022/07/15 Servers