Scrapy 集成 Selenium


设置中间件

集成 selenium driver,实现动态加载

以下方法改变了scrapy异步加载,变为了同步加载,会降低运行效率,当然也可以解决,需要重写 downloader(至少要了解 twisted API)

  • 定义中间件
    class JSPageMiddleware(object):
        """通过 chrome 请求动态网页"""
        def process_request(self, request, spider):
            """selenium 模拟访问"""
            # 判断 spider 实例的 name 
            if spider.name == 'jobbole':
                from scrapy.http import HtmlResponse
                import time
                # 请求 URL
                spider.browser.get(request.url)
                # 放大窗口 / 严谨一点可使用 try
                spider.browser.maximize_window()
                # 避免加载过慢
                time.sleep(3)
                print('request:{0}'.format(request.url))
                # 避免重复下载, 直接调用 HtmlResponse 进行返回
                # current(当前) browser 请求 url, page_source(页面源) 的 html 页面
                # 因为 HtmlResponse 的父类 TextResponse 中 类变量 _DEFAULT_ENCODING 默认为 ascii 码, 根据源页面编码指定编码
                return HtmlResponse(url=spider.browser.current_url, body=spider.browser.page_source,
                                    encoding='utf-8', request=request)
  • 使用 Spider 构造函数,创建 browser 实例
    def __init__(self):
        chrome_option = webdriver.ChromeOptions()
        chrome_option.add_argument('blink-settings=imagesEnabled=false')
        # chrome_option.add_argument('--disable-extensions')
        # chrome_option.add_experimental_option('debuggerAddress', '127.0.0.1:9222')
        self.browser = webdriver.Chrome(executable_path='E:/Template/chromedriver.exe', chrome_options=chrome_option)
        # 使用 super 方法, 防止重复调用
        super(JobboleSpider, self).__init__()
  • 信号

    Scrapy广泛使用信号来通知某些事件的发生。您可以捕获Scrapy项目中的某些信号(例如,使用扩展名)来执行其他任务,或者扩展Scrapy以添加开箱即用的功能。

    即使信号提供了几个参数,捕获它们的处理程序也不需要接受所有参数-信号分配机制将只传递处理程序接收的参数。

    您可以通过Signals API连接到信号(或发送自己的 信号)

    优点:可以允许自定义很多逻辑,且不会侵入到Scrapy的代码当中,跟 Django的设计框架是很相像的

  • 使用信号控制,关闭 browser 实例
    from scrapy.signalmanager import dispatcher
    from scrapy import signals
    
    
  def __init__(self):
      chrome_option = webdriver.ChromeOptions()
      chrome_option.add_argument('blink-settings=imagesEnabled=false')
      # chrome_option.add_argument('--disable-extensions')
      # chrome_option.add_experimental_option('debuggerAddress', '127.0.0.1:9222')
      self.browser = webdriver.Chrome(executable_path='E:/Template/chromedriver.exe', chrome_options=chrome_option)
      # 使用 super 方法, 防止重复调用
      super(JobboleSpider, self).__init__()
      # 调用 dispatcher(分发/调度器) 模块中的 connect 函数
      # 第一个参数 receiver, 接收一个处理方法的名称
      # 第二个参数 signal, 接收一个信号, 传入 signals(信号池) 中的某个信号
      # spider_closed: 当 Spider close 的时候, 给出的信号
      # 分发器调用传入方法
      dispatcher.connect(self.spider_closed, signals.spider_closed)

  def spider_closed(self, spider):
      """当爬虫关闭的时候, 关闭 browser 实例"""
      print('{} closed execute browser quit'.format(spider.name))
      self.browser.quit()



Author: Ming Hui
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source Ming Hui !
 Previous
Selenium 基本使用 Selenium 基本使用
Selenium简介​ 自动化测试框架,最开始是用来做Web自动化测试的,测试网站系统开发。 Selenium 是一个用于Web应用程序测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。支持的浏览器包括IE
2020-08-09
Next 
session 与 cookie 的区别 session 与 cookie 的区别
Cookie 浏览器本地存储方式,存储键值对的格式 简介为什么有cookie的存在,http协议是一种无状态的协议,服务器接收到浏览器的请求后,服务器直接返回内容给浏览器。不管是谁发起的请求 ​ Cookie存储本地,存在隐患。随
2020-08-09 Ming Hui