1.前言

目标网站:武汉市环境保护局(http://hbj.wuhan.gov.cn/viewAirDarlyForestWaterInfo.jspx)。scrapy对接selenium模块抓取空气质量日报数据,需要搭建selenium运行的相应环境,大概搭建方法参见:selenium基本使用;主要是模块的安装和驱动的下载与安装,windows下好像不支持Chorme的无头浏览器,但是有界面的浏览器速度会相对较慢,有条件搭建linux的,用linux下的Chorme headless驱动会快很多;其他的,像火狐等主流浏览器也有对应的驱动,环境搭建差不多,本文用的就是windows下谷歌的驱动(慢就慢点吧);Phantomjs无头浏览器好像现在不能用了。

注意:Chorme浏览器的驱动下载需要结合自己电脑的浏览器版本下载对应的驱动,不然可能驱动用不了。

2.任务分析

抓取武汉市环境保护局的空气质量日报,该网站数据是采用异步加载的;抓包分析可知,整个过程都是对同一个url进行抓取(注:这是一个点,后续编码需要考虑的);因为是用selenium点开网页,所以不需要考虑POST还是GET请求。

3.代码逻辑

3.1 创建scrapy项目

基础的项目创建、爬虫创建及创建后项目的文件结构等内容,就不一一写了,基本使用网上有很多博文,直接上正文了。

3.2 明确抓取字段

来到items.py文件,明确待抓取字段。

# -*- coding: utf-8 -*-
import scrapy class EnvprotectItem(scrapy.Item): # 日期
date = scrapy.Field()
# 点位
loca = scrapy.Field()
# SO2
SO_2 = scrapy.Field()
# NO2
NO_2 = scrapy.Field()
# 吸入颗粒
PMIO = scrapy.Field()
# CO
CO_1 = scrapy.Field()
# O3
O3_d = scrapy.Field()
# 细颗粒物
PM25 = scrapy.Field()
# 空气质量指数
AQIe = scrapy.Field()
# 首要污染物
prmy = scrapy.Field()
# AQI级别
AQIl = scrapy.Field()
# AQI类别
AQIt = scrapy.Field()

3.3 编写爬虫逻辑

到spiders文件夹下的爬虫文件中,开始编写爬虫逻辑。

从第一次selenium请求后的结果中,解析出共多少条数据,以此确定共多少个页面;

从返回的网页源代码中解析数据;

模拟点击“下一页”,获取数据后,继续解析数据,直至解析完所有页面;

selenium模拟点击操作的代码都在middlewares.py的下载中间件中编写;

scrapy会默认过滤掉重复请求(即目标url相同),我们是对同一目标url爬取,因此注意重复请求的设置。

# -*- coding: utf-8 -*-
import math
import scrapy
from EnvProtect.items import EnvprotectItem class ProtectenvSpider(scrapy.Spider):
name = 'ProtectEnv'
# allowed_domains = ['hbj.wuhan.gov.cn']
# start_urls = ['http://hbj.wuhan.gov.cn/']
page=1
pages=1
# 目标url
base_url = 'http://hbj.wuhan.gov.cn/viewAirDarlyForestWaterInfo.jspx' def start_requests(self):
yield scrapy.Request(
url=self.base_url,
callback=self.parse,
dont_filter=True, # 设置不过滤重复请求,scrapy默认过滤重复请求
meta={'index':1} # 该参数判断是否为第一次请求
) def parse(self, response):
"""
第一次请求返回结果中解析出,指定时间段(在middlewares.py文件中指定,后续介绍)内一共有多少条数据;
由于一直是对同一个页面进行爬取(翻页时url没变,数据变了),数据共多少条(页)确定一次就够了
:param response:
:return:
"""
if response.meta['index']:
counts = response.xpath("//div[@class='serviceitempage fr']/span[@class='fl']/text()").extract_first()
counts = int(counts.split(' ')[0])
self.pages = math.ceil(counts / 22) # 确定一共多少个页面 # 解析数据
node_list = response.xpath('//*[@id="tableForm"]/div/div[3]/table/tbody/tr')[1:]
for node in node_list:
item = EnvprotectItem()
item['date'] = node.xpath("./td[1]/text()").extract_first()
item['loca'] = node.xpath("./td[2]/text()").extract_first()
item['SO_2'] = node.xpath("./td[3]/text()").extract_first()
item['NO_2'] = node.xpath("./td[4]/text()").extract_first()
item['PMIO'] = node.xpath("./td[5]/text()").extract_first()
item['CO_1'] = node.xpath("./td[6]/text()").extract_first()
item['O3_d'] = node.xpath("./td[7]/text()").extract_first()
item['PM25'] = node.xpath("./td[8]/text()").extract_first()
item['AQIe'] = node.xpath("./td[9]/text()").extract_first()
item['prmy'] = node.xpath("./td[10]/text()").extract_first()
item['AQIl'] = node.xpath("./td[11]/text()").extract_first()
item['AQIt'] = node.xpath("./td[12]/text()").extract_first()
yield item # 编写爬虫停止运行逻辑
if self.page < self.pages:
self.page += 1
yield scrapy.Request(
url = self.base_url,
callback=self.parse,
dont_filter=True, # 不过滤重复请求,scrapy默认过滤重复请求
meta={'index':0}
)

3.4 编写下载中间件

selenium的所有操作的代码都写在下载中间件中。

# -*- coding: utf-8 -*-
import time
import scrapy
from selenium.webdriver.common.action_chains import ActionChains
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By from EnvProtect.settings import USER_AGENTS as ua class EnvprotectDownloaderMiddleware(object): def __init__(self):
"""
第一页时,不需要点击跳转;其他页面需要模拟点击跳转来获取数据
"""
self.index = 1 def process_request(self, request, spider): if request.url == 'http://hbj.wuhan.gov.cn/viewAirDarlyForestWaterInfo.jspx': self.driver = webdriver.Chrome() # 实例化一个谷歌浏览器
self.driver.get(request.url) # 请求页面
wait = WebDriverWait(self.driver, 30) # 等待页面数据加载,等待30s
try:
# 选择城区
wait.until(EC.frame_to_be_available_and_switch_to_it((By.ID, "iframepage"))) # 等待iframe标签出现
options = self.driver.find_element_by_xpath("//select[@id='typedictionary']/option[2]")
options.click() # 选择时间
self.driver.find_element_by_id('cdateBeginDic').send_keys('2018-11-01')
self.driver.find_element_by_id('cdateEndDic').send_keys('2019-01-20') # 点击查询
self.driver.find_element_by_xpath("//a[@href='#' and @onclick='toQuery(2);']").click()
time.sleep(5) # 指定页面
if not self.index == 1:
self.index += 1 # 第一个页面不用跳转,其他页面需要跳转过去
self.driver.find_element_by_id('goPag').send_keys(str(self.index))
self.driver.find_element_by_id('_goPag').click() # 跳转到该页面
except:
print("Error!")
self.driver.quit() # 构造返回response
html = self.driver.page_source
self.driver.quit()
response = scrapy.http.HtmlResponse(url=request.url, body=html, request=request, encoding='utf-8') return response

3.5 数据保存逻辑

在pipelines文件中编写数据保存逻辑,此处将数据保存为excel文件。

# -*- coding: utf-8 -*-
from openpyxl import Workbook class EnvprotectPipeline(object): def __init__(self):
# 创建excel表格保存数据
self.workbook = Workbook()
self.booksheet = self.workbook.active
self.booksheet.append(['日期', '检测点位', '二氧化硫',
'二氧化氮', '可吸入颗粒物', '一氧化碳',
'臭氧', '细颗粒物', '空气质量指数',
'首要污染物', 'AQI指数级别', 'AQI指数类别']) def process_item(self, item, spider): DATA = [
item['date'], item['loca'], item['SO_2'],
item['NO_2'], item['PMIO'], item['CO_1'],
item['O3_d'], item['PM25'], item['AQIe'],
item['prmy'], item['AQIl'], item['AQIt']
] self.booksheet.append(DATA)
self.workbook.save('./results.xls')
return item

3.6  其他

1.在settings.py文件中打开对应的pipe通道;

2.关闭robot.txt协议

4.完整代码

参见:github地址

scrapy结合selenium抓取武汉市环保局空气质量日报的更多相关文章

  1. [转]使用scrapy进行大规模抓取

    原文:http://www.yakergong.net/blog/archives/500 使用scrapy有大概半年了,算是有些经验吧,在这里跟大家讨论一下使用scrapy作为爬虫进行大规模抓取可能 ...

  2. 在Scrapy项目【内外】使用scrapy shell命令抓取 某网站首页的初步情况

    Windows 10家庭中文版,Python 3.6.3,Scrapy 1.5.0, 时隔一月,再次玩Scrapy项目,希望这次可以玩的更进一步. 本文展示使用在 Scrapy项目内.项目外scrap ...

  3. scrapy定时执行抓取任务

    在ubuntu环境下,使用scrapy定时执行抓取任务,由于scrapy本身没有提供定时执行的功能,所以采用了crontab的方式进行定时执行: 首先编写要执行的命令脚本cron.sh #! /bin ...

  4. Python爬虫实战八之利用Selenium抓取淘宝匿名旺旺

    更新 其实本文的初衷是为了获取淘宝的非匿名旺旺,在淘宝详情页的最下方有相关评论,含有非匿名旺旺号,快一年了淘宝都没有修复这个. 可就在今天,淘宝把所有的账号设置成了匿名显示,SO,获取非匿名旺旺号已经 ...

  5. selenium抓取动态网页数据

    1.selenium抓取动态网页数据基础介绍 1.1 什么是AJAX AJAX(Asynchronouse JavaScript And XML:异步JavaScript和XML)通过在后台与服务器进 ...

  6. selenium抓取视频

    今天闲着没事,用selenium抓取视频保存到本地,只爬取了第一页,只要小于等于5分钟的视频... 为什么不用requests,没有为什么,就因为有些网站正则和xpath都提取不出来想要的东西,要么就 ...

  7. scrapy下载中间件结合selenium抓取全国空气质量检测数据

    1.所需知识补充 1.下载中间件常用函数 process_request(self, request, spider): 当每个request通过下载中间件是,该方法被调用 process_reque ...

  8. 用python+selenium抓取知乎今日最热和本月最热的前三个问题及每个问题的首个回答并保存至html文件

    抓取知乎今日最热和本月最热的前三个问题及每个问题的首个回答,保存至html文件,该html文件的文件名应该是20160228_zhihu_today_hot.html,也就是日期+zhihu_toda ...

  9. 用python+selenium抓取微博24小时热门话题的前15个并保存到txt中

    抓取微博24小时热门话题的前15个,抓取的内容请保存至txt文件中,需要抓取排行.话题和阅读数 #coding=utf-8 from selenium import webdriver import ...

随机推荐

  1. quartus使用串口IP模块

    在quartus平台中使用串口模块的IP,需要使用到platform designer软件来实现. 1.在quartus界面调出IP Catalog界面. 2.在IP catalog中搜索UART,找 ...

  2. 2018.8.15 python中的冒泡法排序

    # 给出一个纯数字列表. 请对列表进行排序. # 思路: # 1.完成a和b的数据交换. 例如, a = 10, b = 24 交换之后, a = 24, b = 10 # 2.循环列表. 判断a[i ...

  3. 2019-2020-1 20199314 《Linux内核原理与分析》 第八周作业

    可执行程序工作原理. 1.ELF(Executable and Linkable Format)可执行和可链接文件,其包含了以下三类: 可重定位文件(Relocatable File):保存着代码和适 ...

  4. CVE-2019-16097:Harbor任意管理员注册漏洞复现

    0x00 Harbor简介 Harbor是一个用于存储和分发Docker镜像的企业级Registry服务器,通过添加一些企业必需的功能特性,例如安全.标识和管理等,扩展了开源Docker Distri ...

  5. Java类、对象、变量、方法

    对象:有状态和行为.例如,一条狗是一个对象,它的状态有:颜色.名字.品种:行为有:摇尾巴.叫.吃等 类:类是一个模板,描述一类对象的行为和状态 对象的行为通过方法来体现,状态就是对象的属性,变量可以是 ...

  6. restapi(9)- caching, akka-http 缓存

    restapi作为前后端交互的枢纽:面对大批量的前端请求,需要确保回复的及时性.使用缓存是一项有效工具.我们可以把多数前端请求的回复response存入缓存,特别是一些需要大量计算才能获取的回复值,更 ...

  7. 搞清楚 Python 的迭代器、可迭代对象、生成器

    很多伙伴对 Python 的迭代器.可迭代对象.生成器这几个概念有点搞不清楚,我来说说我的理解,希望对需要的朋友有所帮助. 1 迭代器协议 迭代器协议是核心,搞懂了这个,上面的几个概念也就很好理解了. ...

  8. VM安装CentOS系统

    本篇文章主要介绍了VMware安装Centos7超详细过程(图文) 1.软硬件准备 软件:推荐使用VMwear,我用的是VMwear 12 镜像:CentOS7 ,如果没有镜像可以在官网下载 :htt ...

  9. PHP创建文件命名中文乱码解决的方法

    PHP创建文件命名中文乱码解决的方法 <pre>iconv('utf-8', 'gbk', $dir); </pre> 因为系统环境是gbk 所以里面的字符也要gbk 编码一致 ...

  10. 史上最详细的C语言冒泡排序算法

    未经同意,请勿转载. void bubbing(){ ] = {,,,,,,,,,};//define init the array //going to the exinternal loop,st ...