別の解決策は、ダウンロードハンドラーまたはダウンロードハンドラーミドルウェアを実装することです。(ダウンローダーミドルウェアの詳細については、スクレイピードキュメントを参照してください)以下は、ヘッドレスphantomjs Webドライバーでセレンを使用するクラスの例です。
1)middlewares.py
スクリプト内でクラスを定義します。
from selenium import webdriver
from scrapy.http import HtmlResponse
class JsDownload(object):
@check_spider_middleware
def process_request(self, request, spider):
driver = webdriver.PhantomJS(executable_path='D:\phantomjs.exe')
driver.get(request.url)
return HtmlResponse(request.url, encoding='utf-8', body=driver.page_source.encode('utf-8'))
2)JsDownload()
クラスを変数DOWNLOADER_MIDDLEWARE
内の変数に追加しますsettings.py
。
DOWNLOADER_MIDDLEWARES = {'MyProj.middleware.MiddleWareModule.MiddleWareClass': 500}
3)HTMLResponse
内部を統合しますyour_spider.py
。応答本文をデコードすると、目的の出力が得られます。
class Spider(CrawlSpider):
# define unique name of spider
name = "spider"
start_urls = ["https://www.url.de"]
def parse(self, response):
# initialize items
item = CrawlerItem()
# store data as items
item["js_enabled"] = response.body.decode("utf-8")
オプションのアドオン:
使用するミドルウェアをさまざまなスパイダーに指示できるようにしたかったので、このラッパーを実装しました。
def check_spider_middleware(method):
@functools.wraps(method)
def wrapper(self, request, spider):
msg = '%%s %s middleware step' % (self.__class__.__name__,)
if self.__class__ in spider.middleware:
spider.log(msg % 'executing', level=log.DEBUG)
return method(self, request, spider)
else:
spider.log(msg % 'skipping', level=log.DEBUG)
return None
return wrapper
ラッパーが機能するためには、すべてのスパイダーが最低限必要です。
middleware = set([])
ミドルウェアを含めるには:
middleware = set([MyProj.middleware.ModuleName.ClassName])
利点:
スパイダーではなくこの方法で実装することの主な利点は、1つのリクエストしか作成しないことです。たとえば、ATのソリューションでは、ダウンロードハンドラーが要求を処理し、応答をスパイダーに渡します。次に、スパイダーはparse_page関数でまったく新しいリクエストを作成します。これは、同じコンテンツに対する2つのリクエストです。