在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中expandtabs()方法的使用
May 18 Python
python制作爬虫并将抓取结果保存到excel中
Apr 06 Python
python处理html转义字符的方法详解
Jul 01 Python
Python 迭代器与生成器实例详解
May 18 Python
Python使用Selenium+BeautifulSoup爬取淘宝搜索页
Feb 24 Python
Python cookbook(数据结构与算法)同时对数据做转换和换算处理操作示例
Mar 23 Python
Python批量删除只保留最近几天table的代码实例
Apr 01 Python
python提取照片坐标信息的实例代码
Aug 14 Python
详解pyinstaller selenium python3 chrome打包问题
Oct 18 Python
python 实现多维数组转向量
Nov 30 Python
Python实现删除某列中含有空值的行的示例代码
Jul 20 Python
python 进制转换 int、bin、oct、hex的原理
Jan 13 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两种去掉数组重复值的方法比较
2014/06/19 PHP
destoon调用企业会员公司形象图片的实现方法
2014/08/21 PHP
php使用Jpgraph创建柱状图展示年度收支表效果示例
2017/02/15 PHP
Laravel如何使用Redis共享Session
2018/02/23 PHP
PHP添加PNG图片背景透明水印操作类定义与用法示例
2019/03/12 PHP
laravel 解决强制跳转 https的问题
2019/10/22 PHP
PHP字符串与数组处理函数用法小结
2020/01/07 PHP
BOOM vs RR BO5 第三场 2.14
2021/03/10 DOTA
JQuery之拖拽插件实现代码
2011/04/14 Javascript
使用js如何实现全选与全不选
2013/12/30 Javascript
javascript计算星座属相(十二生肖属相)示例代码
2014/01/09 Javascript
JS方法调用括号的问题探讨
2014/01/24 Javascript
对Jquery中的ajax再封装,简化操作示例
2014/02/12 Javascript
eclipse导入jquery包后报错的解决方法
2014/02/17 Javascript
javascript中的取反再取反~~没有意义
2014/04/06 Javascript
JavaScript字符串对象toLowerCase方法入门实例(用于把字母转换为小写)
2014/10/17 Javascript
JQuery使用$.ajax和checkbox实现下次不在通知功能
2015/04/16 Javascript
基于JS实现html中placeholder属性提示文字效果示例
2018/04/19 Javascript
解决vue-loader加载不上的问题
2020/10/21 Javascript
[51:53]完美世界DOTA2联赛决赛日 Inki vs LBZS 第二场 11.08
2020/11/10 DOTA
Python3.x和Python2.x的区别介绍
2013/02/12 Python
Python中音频处理库pydub的使用教程
2017/06/07 Python
Python 实现数据库(SQL)更新脚本的生成方法
2017/07/09 Python
python 实现求解字符串集的最长公共前缀方法
2018/07/20 Python
对Pytorch神经网络初始化kaiming分布详解
2019/08/18 Python
python使用opencv实现马赛克效果示例
2019/09/28 Python
PyQt5 QDockWidget控件应用详解
2020/08/12 Python
pytorch __init__、forward与__call__的用法小结
2021/02/27 Python
历史学专业个人的自我评价
2013/10/13 职场文书
课堂教学改革实施方案
2014/03/17 职场文书
党员自我剖析材料
2014/08/31 职场文书
弘扬焦裕禄精神走群众路线思想汇报
2014/09/12 职场文书
中学生运动会通讯稿大全
2014/09/18 职场文书
教师节标语大全
2014/10/07 职场文书
关于有小孩的离婚协议书
2014/10/26 职场文书
小学音乐课教学反思
2016/02/18 职场文书