• Scrapy实战篇(六)之Scrapy配合Selenium爬取京东信息(上)


    在之前的一篇实战之中,我们已经爬取过京东商城的文胸数据,但是前面的那一篇其实是有一个缺陷的,不知道你看出来没有,下面就来详细的说明和解决这个缺陷。

    我们在京东搜索页面输入关键字进行搜索的时候,页面的返回过程是这样的,它首先会直接返回一个静态的页面,页面的商品信息大致是30个,之所以说是大致,因为有几个可能是广告商品,之后,当我们鼠标下滑的使用,京东后台使用Ajax技术加载另外的30个商品数据,我们看上去是60个数据,其实这60个数据是分两次加载出来的,而且只是在你鼠标下滑到一定的位置才会加载那另外的30个数据。

    当你点击页面最后的第二页的时候,仔细观察新的url你会发现它的页面显示是第三页。
    下面是初始第一面和点击第二页之后的url

    # 第一页的url
    https://search.jd.com/Search?keyword=%E6%89%8B%E6%9C%BA&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&wq=%E6%89%8B%E6%9C%BA&cid2=653&cid3=655&page=1&s=1&click=0
    
    # 点击第二页的url
    https://search.jd.com/Search?keyword=%E6%89%8B%E6%9C%BA&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&wq=%E6%89%8B%E6%9C%BA&cid2=653&cid3=655&page=3&s=59&click=0
    

    page参数一个是1,一个是3。
    因此可以得知,京东的第二页的信息是使用Ajax加载出来的,而不是直接请求url的形式。如果我们想要拿到另外的30个信息,一方面是需要js渲染,另一方面是实现滚动条下拉,触发Ajax请求。

    知道了过程,下面就是着手解决这个问题,由于Scrapy框架只能加载静态数据,因此我们需要另外的工具来配合Scrapy实现爬取页面的完整信息。

    我们的技术路线是这样的,使用selenium加Firefox来实现目的。
    实现的过程是这样的,将selenium作为scrapy的下载中间件,执行js脚本实现滚动条的下拉,并且实现js的渲染。

    下面就来演示。

    spider.py文件

    from scrapy import Spider,Request
    from selenium import webdriver
    
    
    class JingdongSpider(Spider):
        name = 'jingdong'
    
        def __init__(self):
            self.browser = webdriver.Firefox()
            self.browser.set_page_load_timeout(30)
    
        def closed(self,spider):
            print("spider closed")
            self.browser.close()
    
        def start_requests(self):
            start_urls = ['https://search.jd.com/Search?keyword=%E6%96%87%E8%83%B8&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&suggest=1.his.0.0&page={}&s=1&click=0'.format(str(i)) for i in range(1,2,2)]
            for url in start_urls:
                yield Request(url=url, callback=self.parse)
    
    
        def parse(self, response):
            selector = response.xpath('//ul[@class="gl-warp clearfix"]/li')
            print(len(selector))
            print('---------------------------------------------------')
    

    这里将webdriver定义在spider文件的好处是,不需要每一次请求url都打开和关闭浏览器。
    其中的closed()方法,是在爬虫程序结束之后,自动关闭浏览器。
    由于这里是演示之用,我们就以一个页面来测试,看一下最后的结果是不是返回60条数据,如果是60条左右就证明我们的selenium起作用了,如果仅仅是30条左右的数据,就证明失败。

    middlewares.py

    下面的这个文件是主要逻辑实现

    from scrapy.http import HtmlResponse
    from selenium.common.exceptions import TimeoutException
    import time
    
    class SeleniumMiddleware(object):
        def process_request(self, request, spider):
            if spider.name == 'jingdong':
                try:
                    spider.browser.get(request.url)
                    spider.browser.execute_script('window.scrollTo(0, document.body.scrollHeight)')
                except TimeoutException as e:
                    print('超时')
                    spider.browser.execute_script('window.stop()')
                time.sleep(2)
                return HtmlResponse(url=spider.browser.current_url, body=spider.browser.page_source,
                                    encoding="utf-8", request=request)
    

    在程序中,我们执行了js脚本,来实现滚动条下拉,触发Ajax请求,之后我们简短的等待,来加载Ajax。 在scrapy官方文档中,对下载中间件有着比较详细的说明,当某个下载中间件返回的是response对象的时候,之后的下载中间件将不会被继续执行,而是直接返回response对象。

    之后,我们只需要在设置中将当前的下载中间件添加到settings.py文件中,就可以实现了。

    运行程序,会发现自动打开了Firefox浏览器,并且实现了滚动条的下拉,关闭浏览器。控制台打印信息如下。

    不妨多试验几个页面,会发现效果也是一样的。

  • 相关阅读:
    python之isinstance和issubclass
    python中类的继承
    python中面向对象
    python中常用的内置模块
    Python常用模块
    python中的常用内置模块
    python中的包、模块及导入
    python中的内置函数(二)
    国内7大核心期刊
    PS学习列表
  • 原文地址:https://www.cnblogs.com/cnkai/p/7570116.html
Copyright © 2020-2023  润新知