美文网首页【收集】Python网络爬虫
Python网络爬虫实战之十四:Scrapy结合scrapy-s

Python网络爬虫实战之十四:Scrapy结合scrapy-s

作者: 27efec53a72d | 来源:发表于2018-08-25 14:18 被阅读377次

    目录:Python网络爬虫实战系列

    正文:

    一、Scrapy爬取动态网页数据的原理

    之前我们学习的内容都是抓取静态页面,每次请求,它的网页全部信息将会一次呈现出来。 但是,像比如一些购物网站,他们的商品信息都是js加载出来的,并且会有ajax异步加载。像这样的情况,直接使用scrapy的Request请求是拿不到我们想要的信息的,比如京东商城的商品列表中的价格、店铺名称、评论数量。解决的方法就是使用scrapy-splash。

    scrapy-splash加载js数据是基于Splash来实现的,Splash是一个Javascript渲染服务。它是一个实现了HTTP API的轻量级浏览器,Splash是用Python实现的,同时使用Twisted和QT,而我们使用scrapy-splash最终拿到的response相当于是在浏览器全部渲染完成以后,拿到的渲染之后的网页源代码。

    二、爬取之前的环境部署

    1、安装docker

    在windows环境下,安装docker简便的方法是使用docker toolbox,由于Docker引擎的守护进程使用的是Linux的内核,所以我们不能够直接在windows中运行docker引擎。而是需要在你的机器上创建和获得一个Linux虚拟机,用这个虚拟机才可以在你的windows系统上运行Docker引擎,docker toolbox这个工具包里面集成了windows环境下运行docker必要的工具,当然也包括虚拟机了。

    首先下载docker toolbox,
    官方下载地址:https://www.docker.com/products/docker-desktop

    执行安装程序,默认情况下,你的计算机会安装以下几个程序

    • Windows版的Docker客户端
    • Docker Toolbox管理工具和ISO镜像
    • Oracle VM 虚拟机
    • Git 工具

    当然,如果你之前已经安装过了Oracle VM 虚拟机 或者 Git 工具 ,那么你在安装的时候可以取消勾选这两个内容,之后,你只需要狂点下一步即可。安装完毕以后,找到Docker Quickstart Terminal图标,双击运行,稍等它自己配置一小段时间,你会看到以下的界面

    scrapy1.png

    请注意上面画红框的地方,这是默认分配给你的ip,下面会用到。至此,docker工具就已经安装好了。

    2、安装Splash

    双击运行Docker Quickstart Terminal,输入以下内容

    docker pull scrapinghub/splash 
    

    这个命令是拉取Splash镜像,等待一算时间,就可以了。

    下面就是启动Splash

    docker run -p 8050:8050 scrapinghub/splash
    

    这个命令就是在计算机的8050端口启动Splash渲染服务
    你会看到以下的图示内容。

    scrapy2.png

    这个时候,打开你的浏览器,输入192.168.99.100:8050你会看到出现了这样的界面。

    scrapy3.png

    你可以在上图红色框框的地方输入任意的网址,点击后面的Render me! 来查看渲染之后的样子。

    3、安装scrapy-splash

    pip install scrapy-splash
    

    至此,我们的准备环节已经全部结束了。

    4、如果以上操作遇到困难

    以上操作如遇到困难,请参考 Docker Toolbox for Windows 之安装二三事解决

    三、实战爬取京东商品列表中的商品信息

    网页地址:https://list.jd.com/list.html?cat=652,654,831

    1、创建项目

    scrapy startproject jdcamera
    

    创建项目后在spider目录下新建 camera.py 文件

    项目结构截图


    scrapy4.png

    2、items.py代码

    import scrapy
    
    
    class JdcameraItem(scrapy.Item):
        # 名称
        name = scrapy.Field()
        # 链接
        link = scrapy.Field()
        # 价格
        price = scrapy.Field()
        # 销售店铺
        owner = scrapy.Field()
        # 评论数
        comment = scrapy.Field()
    

    3、camera.py代码

    import scrapy
    from jdcamera.items import JdcameraItem
    from scrapy.http import Request
    import re
    from scrapy_splash import SplashRequest
    
    
    class CameraSpider(scrapy.Spider):
        name = "jdcamera"
        allowed_domains = ["list.jd.com"]
        start_urls = (
            'https://list.jd.com/list.html?cat=652,654,831',
            # "https://list.jd.com/list.html?cat=652,654,831&page=1&sort=sort_totalsales15_desc&trans=1&JL=6_0_0#J_main"
        )
    
        def start_requests(self):
            for url in self.start_urls:
                yield SplashRequest(url=url, callback=self.parse,
                                    args={'wait': 1}, endpoint='render.html')
    
        def parse(self, response):
            for sel in response.xpath('//*[@id="plist"]/ul/li/div[@class="gl-i-wrap j-sku-item"]'):
                item = JdcameraItem()
                # 链接
                item["link"] = "http:" + str(sel.xpath('div[1]/a/@href').extract())[2:-2]
                # 价格
                item["price"] = sel.xpath('div[2]/strong[1]/i/text()').extract()
                # 商品名称
                temp = str(sel.xpath('div[3]/a/em/text()').extract())
                pattern = re.compile("[\u4e00-\u9fa5]+.+\w")  # 从第一个汉字起 匹配商品名称
                good_name = re.search(pattern, temp)
                item["name"] = good_name.group()
                # 评论数
                item["comment"] = sel.xpath('div[4]/strong/a/text()').extract()
                # 销售店铺
                item["owner"] = sel.xpath('div[5]/span/a/text()').extract()
                # 提取完后返回item
                yield item
    
            # 通过循环自动爬取127页的数据
            for i in range(2, 128):
                # 通过上面总结的网址格式构造要爬取的网址
                url = "https://list.jd.com/list.html?cat=652,654,831&page=" + str(i) + "&sort=sort_totalsales15_desc&trans=1&JL=6_0_0"
                # 通过yield返回Request,并指定要爬取的网址和回调函数
                # 实现自动爬取
                # yield Request(url, callback=self.parse)
                yield SplashRequest(url=url, callback=self.parse, args={'wait': 1}, endpoint='render.html')
    

    4、pipelines.py代码

    import codecs
    import json
    
    
    class JdcameraPipeline(object):
        def __init__(self):
            # 此时存储到的文件是mydata2.json,不与之前存储的文件mydata.json冲突
            self.file = codecs.open('D:/DataguruPyhton/PythonSpider/images/京东数码相机.txt', "wb", encoding="utf-8")
    
        def process_item(self, item, spider):
            # 每一页中包含多个商品信息,所以可以通过循环,每一次处理一个商品
            # 其中len(item["name"])为当前页中商品的总数,依次遍历
            # 将当前页的第j个商品的名称赋值给变量name
            name = item["name"]
            price = item["price"]
            owner = item["owner"]
            comment = item["comment"]
            link = item["link"]
            # 将当前页下第j个商品的name、price、comnum、link等信息处理一下,重新组合成一个字典
            goods = {"name": name, "price": price, "owner": owner, "comment": comment, "link": link}
            # 将组合后的当前页中第j个商品的数据写入json文件
            i = json.dumps(dict(goods), ensure_ascii=False)
            line = i + '\n'
            self.file.write(line)
            # 返回item
            return item
    
        def close_spider(self, spider):
            self.file.close()
    

    5、settings.py代码

    BOT_NAME = 'jdcamera'
    
    SPIDER_MODULES = ['jdcamera.spiders']
    NEWSPIDER_MODULE = 'jdcamera.spiders'
    
    # Crawl responsibly by identifying yourself (and your website) on the user-agent
    USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'
    
    # Obey robots.txt rules
    ROBOTSTXT_OBEY = False
    
    # Disable cookies (enabled by default)
    COOKIES_ENABLED = False
    
    # Override the default request headers:
    DEFAULT_REQUEST_HEADERS = {
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        'Accept-Language': 'en',
        'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
    }
    
    # 渲染服务的url
    SPLASH_URL = 'http://192.168.99.100:8050'
    
    # Enable or disable downloader middlewares
    # See https://doc.scrapy.org/en/latest/topics/downloader-middleware.html
    DOWNLOADER_MIDDLEWARES = {
        'scrapy_splash.SplashCookiesMiddleware': 723,
        'scrapy_splash.SplashMiddleware': 725,
        'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810,
    }
    
    ITEM_PIPELINES = {
        'jdcamera.pipelines.JdcameraPipeline': 300,  # 实现保存到txt文件
    }
    
    # 去重过滤器
    DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter'
    # 使用Splash的Http缓存
    HTTPCACHE_STORAGE = 'scrapy_splash.SplashAwareFSCacheStorage'
    
    

    6、运行项目

    scrapy crawl jdcamera
    

    结果如图:


    scrapy5.png

    相关文章

      网友评论

        本文标题:Python网络爬虫实战之十四:Scrapy结合scrapy-s

        本文链接:https://www.haomeiwen.com/subject/wtdxiftx.html