在scrapy中使用phantomJS實現(xiàn)異步爬取的方法
使用selenium能夠非常方便的獲取網(wǎng)頁的ajax內容,并且能夠模擬用戶點擊和輸入文本等諸多操作,這在使用scrapy爬取網(wǎng)頁的過程中非常有用。
網(wǎng)上將selenium集成到scrapy的文章很多,但是很少有能夠實現(xiàn)異步爬取的,下面這段代碼就重寫了scrapy的downloader,同時實現(xiàn)了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實現(xiàn)異步爬取的方法就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
python 通過logging寫入日志到文件和控制臺的實例
下面小編就為大家分享一篇python 通過logging寫入日志到文件和控制臺的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-04-04Python數(shù)據(jù)類型之String字符串實例詳解
這篇文章主要介紹了Python數(shù)據(jù)類型之String字符串,結合實例形式詳細講解了Python字符串的概念、定義、連接、格式化、轉換、查找、截取、判斷等常見操作技巧,需要的朋友可以參考下2019-05-05django實現(xiàn)圖片上傳數(shù)據(jù)庫并顯示
這篇文章主要為大家詳細介紹了django實現(xiàn)圖片上傳數(shù)據(jù)庫并顯示,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-08-08pycharm?使用conda虛擬環(huán)境的詳細配置過程
這篇文章主要介紹了pycharm?使用conda虛擬環(huán)境,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-03-03python自動化測試之DDT數(shù)據(jù)驅動的實現(xiàn)代碼
這篇文章主要介紹了python自動化測試之DDT數(shù)據(jù)驅動的實現(xiàn)代碼,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-07-07