另一种解决方案是实现下载处理程序或下载处理程序中间件。(有关下载器中间件的更多信息,请参见scrapy 文档)以下是使用 selenium 和 headless phantomjs webdriver 的示例类:
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])
优点:
以这种方式而不是在蜘蛛中实现它的主要优点是您最终只会发出一个请求。例如在 AT 的解决方案中:下载处理程序处理请求,然后将响应交给蜘蛛。蜘蛛然后在它的 parse_page 函数中发出一个全新的请求——这是对相同内容的两个请求。