目录
  • 一、传统爬虫的问题
  • 1.实际案例
  • 二、scrapy解决动态网页渲染问题的策略
  • 三、安装使用scrapy-splash
    • 1.安装Docker
    • 2.安装splash镜像
    • 3.安装scrapy-splash
  • 四、项目实践
    • 五、总结与思考

      一、传统爬虫的问题

      scrapy爬虫与传统爬虫一样,都是通过访问服务器端的网页,获取网页内容,最终都是通过对于网页内容的分析来获取数据,这样的弊端就在于他更适用于静态网页的爬取,而面对js渲染的动态网页就有点力不从心了,因为通过js渲染出来的动态网页的内容与网页文件内容是不一样的

      1.实际案例

      腾讯招聘:https://careers.tencent.com/search.html

      scrapy爬虫遇到js动态渲染问题

      这个网站第一眼看过去是非常中规中矩的结构也很鲜明,感觉是很好爬的样子,但是当你查看他的网页文件的时候,就会发现:

      scrapy爬虫遇到js动态渲染问题

      网页文件并没有太多的内容,全部是引用了js做的动态渲染,所有数据都在js中间,这就使我们无法对于网页的结构进行分析来进行爬取数据

      那我们如何,获取到它实际显示的页面,然后对页面内容进行分析呢?

      二、scrapy解决动态网页渲染问题的策略

      目前scrapy解决动态网页渲染问题的主要有以下三种的解决方法:

      seleium+chrome

      就是传统的结合浏览器进行渲染,优点就在于,浏览器能访问什么,他就能够获取到什么,缺点也很明显,因为它需要配合浏览器,所以它的速度很慢。

      selenium+phantomjs

      与上一种的方式一样,但是不需要开浏览器。

      scrapy-splash(推荐)

      而scrapy-splash与以上两种方法对比,它更加快速轻量,由于,他是基于twisted和qt开发的轻量浏览器引擎,并提供了http api,速度更快,最重要的是他能够与scrapy非常完美的融合。

      三、安装使用scrapy-splash

      1.安装Docker

      由于ScrapySplash要在docker里使用,我们先安装docker,过程比较复杂痛苦,略

      在安装的过程中有一个非常严峻的问题,那就是docker,需要开启win10 hyper虚拟服务,这与你在电脑上安装的VM是相冲突的,所以在使用docker,的时候无法使用VM虚拟机,而且每次切换时都需要重启电脑,目前这个问题暂时无法解决。

      2.安装splash镜像

      docker run -p 8050:8050 scrapinghub/splash

      这个过程异常异常的慢,而且必须是国内的镜像,才能够下载下来。

      所以我配置了两个国内的下载IP,一个网易的,一个阿里云的。

      {
        "registry-mirrors": [
          "https://registry.docker-cn.com",
          "http://hub-mirror.c.163.com",
          "https://docker.mirrors.ustc.edu.cn"
        ],
        "insecure-registries": [],
        "debug": true,
        "experimental": false
      }
      

      下载完成过后,打开浏览器访问:http://localhost:8050/

      scrapy爬虫遇到js动态渲染问题

      这就表示已经安装完成了,命令行不能关闭哦

      3.安装scrapy-splash

      pip install scrapy-splash

      python没有花里胡哨的安装过程。

      四、项目实践

      1.项目的创建和配置过程略

      2.settings.py的配置

      PIDER_MIDDLEWARES = {
         'scrapy_splash.SplashDeduplicateArgsMiddleware': 100,
      }
      DOWNLOADER_MIDDLEWARES = {
          'scrapy_splash.SplashCookiesMiddleware': 723,
          'scrapy_splash.SplashMiddleware': 725,
          'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810,  # 不配置查不到信息
      }
      
      HTTPCACHE_ENABLED = True
      HTTPCACHE_EXPIRATION_SECS = 0
      HTTPCACHE_DIR = 'httpcache'
      
      SPLASH_URL = "http://localhost:8050/"  # 自己安装的docker里的splash位置
      # DUPEFILTER_CLASS = "scrapy_splash.SplashAwareDupeFilter"
      HTTPCACHE_STORAGE = 'scrapy_splash.SplashAwareFSCacheStorage'
      
      

      3.爬虫的设计

          def start_requests(self):
              splah_args = {
                  "lua_source": """
                  function main(splash, args)
                    assert(splash:go(args.url))
                    assert(splash:wait(0.5))
                    return {
                      html = splash:html(),
                      png = splash:png(),
                      har = splash:har(),
                    }
                  end
                  """
              }
              headers = {
                  'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) '
                                'Chrome/72.0.3626.109 Safari/537.36',
              }
              yield SplashRequest(url=self.start_url, callback=self.parse, args=splah_args,
                                  headers=headers)
      

      这里我们编写一个初始化的start_requests方法,这个方法是继承父类的。

      注意我们最后的请求方式SplashRequest,我们不再使用Request,而是使用scrapy-splash的请求方式,这里也体现了它与scope框架的完美融合。

      至于里面的参数,就没有必要介绍了,其中要注意两个参数argscallback

      • args是配置信息可以参照http://localhost:8050/中的
      • callback下一级处理方法的函数名,最后的方法一定要指向self.parse,这是scrapy迭代爬取的灵魂。

      4.解析打印数据

          def parse(self, response):
              print(response.text)
              job_boxs = response.xpath('.//div[@class="recruit-list"]')
              for job_box in job_boxs:
                  title = job_box.xpath('.//a/h4/text()').get()
                  print(title)
      

      这是通过渲染以后的网页数据

      scrapy爬虫遇到js动态渲染问题

      这里我们直接获取职位的标题

      scrapy爬虫遇到js动态渲染问题

      这就表明scrapy爬虫应对动态网页渲染问题已经解决,也就意味着scrapy能够处理大部分的网页,并可以应对一些图形验证问题

      五、总结与思考

      之后遇到的问题,当我们获取到了,职位列表过后,当我们需要访问详情页的时候,我们就必须获取详情页的链接,但是腾讯非常的聪明,并没有采用超链接的方式进行跳转,而是通过用户点击事件,然后通过js跳转,这就造成了我们无法获取详情页的链接。

      当我沮丧的时候,我认真的检查了浏览器与服务器的数据交换中,其实它的数据也是通过js进行后台请求得到的,所以通过对大量的数据进行采集,最终找到了他的数据接口(贼开心!!!)

      scrapy爬虫遇到js动态渲染问题

      这时候我们就要做取舍了,我们想要的是所有数据,并不是渲染出来的网页,与解析网页内容相比,直接通过它的接口获取json数据,更加快捷方便,速度更快,所以我们就要做出取舍,在这里直接获取接口数据将更好,错误率会更低,速度也会更快。

      其实大部分的动态网页的渲染,都存在与数据端进行请求交互数据,当然也存在一些,直接把数据存在js中间,然后再通过js渲染到网页上,这时候scrapy-splash就可以发挥价值了,尤其是在一些验证码,图形验证方面更加突出。随着前端技术的不断发展,前端对数据的控制更加灵活多样,这也要求爬虫的逻辑也需要不断的跟进,也要求使用新的工具,新的技术,在不断的探索实践中跟上时代的步伐。

      声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。