Python-Scrapy抓取中国空气质量全站数据-ChinaArea案例

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

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

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

    《Python-Scrapy抓取中国空气质量全站数据-ChinaArea案例》 一级域名页面

    1.2. 爬虫起始页面

    《Python-Scrapy抓取中国空气质量全站数据-ChinaArea案例》 抓取起始页面
    1.3. 从上图随便点个城市链接进去,找到月份链接
    《Python-Scrapy抓取中国空气质量全站数据-ChinaArea案例》 白城的空气质量不咋滴
    1.4. 这是我们需要抓取的数据字段 加上城市的字段一共有十个了.
    《Python-Scrapy抓取中国空气质量全站数据-ChinaArea案例》 找到我们需要爬取的数据字段

  2. 分析网页数据格式
    2.1. 第一个页面为静态

    《Python-Scrapy抓取中国空气质量全站数据-ChinaArea案例》 第一个页面
    《Python-Scrapy抓取中国空气质量全站数据-ChinaArea案例》 静态页面

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

《Python-Scrapy抓取中国空气质量全站数据-ChinaArea案例》 第二个页面

《Python-Scrapy抓取中国空气质量全站数据-ChinaArea案例》 动态页面

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

《Python-Scrapy抓取中国空气质量全站数据-ChinaArea案例》 第三个页面

《Python-Scrapy抓取中国空气质量全站数据-ChinaArea案例》 动态页面

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

  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. 抓取过程

    《Python-Scrapy抓取中国空气质量全站数据-ChinaArea案例》 抓取过程

  2. 抓取结果

    《Python-Scrapy抓取中国空气质量全站数据-ChinaArea案例》 抓取结果

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

    老师: 《Python-Scrapy抓取中国空气质量全站数据-ChinaArea案例》

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

    原文作者:空山老师
    原文地址: https://www.jianshu.com/p/c4234432a2f1
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞