本节知识点主要是Scrapy对接selenium
目标抓取每个城市空气质量指数日历史数据
-
分析网页数据结构
1.1. 一级域名页面
一级域名页面
1.2. 爬虫起始页面
抓取起始页面
1.3. 从上图随便点个城市链接进去,找到月份链接
白城的空气质量不咋滴
1.4. 这是我们需要抓取的数据字段 加上城市的字段一共有十个了.
找到我们需要爬取的数据字段 -
分析网页数据格式
2.1. 第一个页面为静态
第一个页面
静态页面
2.2. 第二个页面为动态页面
第二个页面
动态页面
2.3. 第三个页面为动态页面
第三个页面
动态页面
除了第一个页面为静态其它页面均问动态
-
思路:第一个页面为静态我们采用平常方式发送请求,之后页面我们采用selenium+Chrome抓取。
-
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,
}
-
抓取过程
抓取过程 -
抓取结果
抓取结果
老师:同学们!Are you ready?!!
老师:
同学:老师我想...
(原创文章,转载请注明出处)
网友评论