美文网首页爬虫技术
Python-Scrapy抓取中国空气质量全站数据-ChinaA

Python-Scrapy抓取中国空气质量全站数据-ChinaA

作者: 8f3a71b379c1 | 来源:发表于2018-08-01 22:22 被阅读1632次

    本节知识点主要是Scrapy对接selenium

    目标抓取每个城市空气质量指数日历史数据

    1. 分析网页数据结构
      1.1. 一级域名页面


      一级域名页面

      1.2. 爬虫起始页面


      抓取起始页面
      1.3. 从上图随便点个城市链接进去,找到月份链接
      白城的空气质量不咋滴
      1.4. 这是我们需要抓取的数据字段 加上城市的字段一共有十个了.
      找到我们需要爬取的数据字段
    2. 分析网页数据格式
      2.1. 第一个页面为静态


      第一个页面
      静态页面

    2.2. 第二个页面为动态页面


    第二个页面
    动态页面

    2.3. 第三个页面为动态页面


    第三个页面
    动态页面

    除了第一个页面为静态其它页面均问动态

    1. 思路:第一个页面为静态我们采用平常方式发送请求,之后页面我们采用selenium+Chrome抓取。

    2. OK,上代码!
      items.py

    import scrapy
    
    class ChinaareaItem(scrapy.Item):
        # 城市
        city = scrapy.Field()
        # 日期
        date = scrapy.Field()
        # 空气质量指数
        aqi = scrapy.Field()
        # 空气质量等级
        level = scrapy.Field()
        # pm2.5
        pm2_5 = scrapy.Field()
        # pm10
        pm10 = scrapy.Field()
        # 二氧化硫
        so2 = scrapy.Field()
        # 一氧化碳
        co = scrapy.Field()
        # 二氧化氮
        no2 = scrapy.Field()
        # 臭氧
        o3 = scrapy.Field()
    
        # 数据源
        source = scrapy.Field()
        # 抓取时间
        utc_item =scrapy.Field()
    

    spider.py

    # -*- coding: utf-8 -*-
    import scrapy
    from ChinaArea.items import ChinaareaItem
    
    class AreaSpider(scrapy.Spider):
        name = 'area'
        allowed_domains = ['aqistudy.cn']
        base_url = "https://www.aqistudy.cn/historydata/"
        start_urls = [base_url]
    
        def parse(self, response):
            print("正在爬取城市信息")
            Url_list = response.xpath('//div[@class="all"]/div[@class="bottom"]//a/@href').extract()
            city_list = response.xpath('//div[@class="all"]/div[@class="bottom"]//a/text()').extract()
            for Url, city in zip(Url_list, city_list):
                link = self.base_url + Url
                yield scrapy.Request(url=link, callback=self.parse_mouth, meta={"city":city})
    
        def parse_mouth(self, response):
            print("正在爬取城市月份")
            Url_list = response.xpath('//tr/td/a/@href').extract()
    
            for Url in Url_list:
                link = self.base_url + Url
                print(link)
                yield scrapy.Request(url=link, callback=self.parse_day, meta={"city":response.meta['city']})
    
        def parse_day(self, response):
            print("正在爬取最终数据")
            node_list = response.xpath('//tr')
            node_list.pop(0)
    
            for node in node_list:
                item = ChinaareaItem()
                item['city'] = response.meta['city']
                item['date'] = node.xpath('./td[1]/text()').extract_first()
                item['aqi'] = node.xpath('./td[2]/text()').extract_first()
                item['level'] = node.xpath('./td[3]//text()').extract_first()
                item['pm2_5'] = node.xpath('./td[4]/text()').extract_first()
                item['pm10'] = node.xpath('./td[5]/text()').extract_first()
                item['so2'] = node.xpath('./td[6]/text()').extract_first()
                item['co'] = node.xpath('./td[7]/text()').extract_first()
                item['no2'] = node.xpath('./td[8]/text()').extract_first()
                item['o3'] = node.xpath('./td[9]/text()').extract_first()
                yield item
    

    middlewares.py

    from selenium import webdriver
    from time import sleep
    import scrapy
    
    
    class AreaMiddleware(object):
        def process_request(self, request, spider):
            self.driver = webdriver.Chrome()
            # 判断动态页面采用 selenium+Chrome抓取
            if request.url != "https://www.aqistudy.cn/historydata/":
                self.driver.get(request.url)
                sleep(1.5)  # 等待js渲染完成
                html = self.driver.page_source
                self.driver.quit()
                # 构造返回response响应体
                return scrapy.http.HtmlResponse(url=request.url, body=html,
                                            encoding="utf-8",request=request)
    

    pipelines.py

    import json
    from datetime import datetime
    
    # 数据源和抓取时间存储(养成好习惯哈)
    class SpiderPipeline(object):
        def process_item(self, item, spider):
            item['source'] = spider.name
            item['utc_time'] = str(datetime.utcnow())
            return item
    
    # json文件存储
    class ChinaareaPipeline(object):
        def open_spider(self, spider):
            self.file = open("area.json", "w")
    
        def process_item(self, item, spider):
            content = json.dumps(dict(item)) + "\n"
            self.file.write(content)
            return item
    
        def close_spider(self, spider):
            self.file.close()
    

    settings.py

    # 注册下载器中间件
    DOWNLOADER_MIDDLEWARES = {
        'ChinaArea.middlewares.ChinaareaSpiderMiddleware': 543,
    }
    # 注册管道
    ITEM_PIPELINES = {
        'ChinaArea.pipelines.ChinaareaPipeline': 300,
        'ChinaArea.pipelines.SpiderPipeline': 200,
    }
    
    1. 抓取过程


      抓取过程
    2. 抓取结果


      抓取结果

      老师:同学们!Are you ready?!!
      同学:老师我想...

      老师:

    (原创文章,转载请注明出处)

    相关文章

      网友评论

        本文标题:Python-Scrapy抓取中国空气质量全站数据-ChinaA

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