python爬取中国空气质量在线监测平台分析数据【已更新】
**本文介绍如何爬取诸如北京等城市的空气污染物浓度数据,并附有完整代码,统统解决你们找不到数据的科研问题!干货满满!!!
2021年1月12日更新
看了很多小伙伴的评论,发现我的代码被官方给“制裁”了【设置反扒了】,前段时间一直在准备秋招和毕设就没有时间反反扒(解决不能爬去的问题),如今捣鼓了一下午,终于还是搞定了!
刚刚爬取的程序结果如下:
这是我刚刚更新的本地数据库的截图!
好了,言归正传,看一下你们需要的数据应该是长这样的
这个网站有我们需要的空气污染物数据,时间跨度为2014年1月至最新日期,完美!
那么如何才能不费吹灰之力的获取到这些数据呢[实际上我第三次爬取该网站才成功>_<]?
先介绍我在爬取过程遇到的坑!让你觉得这并不是一件容易的事,哈哈哈!
困难1:
打开开发者工具(F12),如图:
这是我第一次想要爬该网站数据的时候,遇到的反爬虫情况!这是完全不给我机会呗,连网页源代码都不让我看呗! 【放弃】
最终处理方法有两个:
第一:换浏览器,如QQ浏览器,火狐浏览器
【更新】:火狐浏览器目前也不行了,也被官方设置反扒了
第二:采用断点方式(这里不具体介绍了,尽管我一开始采用的是断点)
第三:直接在网站上输入:view-source:网址即可 【推荐】
困难2:
在获取到网页源代码之后,你会发现你想要获取的数据就在tr标签里,但是你通过Beautifulsoup、Xpath等各种方式,都无法获取数据标签,最终他只会给你返回方框的代码,而你想要的椭圆形的代码就是不给你! 【放弃】
原因: 首先我们提取标签的代码是没问题的,这是因为这样的 表格数据 是通过js渲染得到的,你所需要的数据是通过ajax请求的数据包中响应数据是经过加密的密文数据…然后你就需要进行js解密,反正过程还是挺复杂的,这让没学过js的我无能为力!
解决方案:
既然是通过ajax请求获取的数据,何不从另一个角度思考-----selenium
准备工具: Firefox浏览器并配置好他的环境 ,过程并不难,百度一下即可,这一步如果有困难的可评论在下方
这里之所以用火狐而不是Chrome,原因也是Chrome无法打开网页源代码
【更新】:火狐目前也不行了
目前正确的做法是“伪装浏览器”,因为很多网站(如淘宝等)都设置了对selenium的检测,防止他们的网站被恶意爬取,检测基本原理是检测当前浏览器窗口下的 window.navigator 对象是否包含 webdriver 这个属性。因为在正常使用浏览器的情况下,这个属性是 undefined,然而一旦我们使用了 Selenium,Selenium 会给 window.navigator 设置 webdriver 属性。很多网站就通过 JavaScript 判断如果 webdriver 属性存在,那就直接屏蔽。具体的原理我就不介绍了,直接贴代码:
from selenium import webdriver
from selenium.webdriver import ChromeOptions
option = ChromeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation'])
option.add_experimental_option('useAutomationExtension', False)
browser = webdriver.Chrome(options=option)
browser.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {'source': 'Object.defineProperty(navigator, "webdriver", {get: () => undefined})'
})
option = webdriver.ChromeOptions()
option.add_argument("start-maximized")
option.add_argument("--disable-blink-features=AutomationControlled")
option.add_experimental_option("excludeSwitches", ["enable-automation"])
option.add_experimental_option("useAutomationExtension", False)
browser = webdriver.Chrome(options=option)
browser.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument",{'source':'''Object.defineProperty(navigator, 'webdriver', {get: () =>false'''})
感兴趣的可以参考https://zhuanlan.zhihu.com/p/191033198
接下来对代码进行讲解:
第一步:
def get_date(url):response = requests.get(url)dates = []try:if response.status_code ==200:response = response.textsoup = BeautifulSoup(response, 'lxml')dates_ = soup.find_all('li')for i in dates_:if i.a: # 去除空值li = i.a.text # 提取li标签下的a标签date = re.findall('[0-9]*', li) # ['2019', '', '12', '', '']year = date[0]month = date[2]if month and year: # 去除不符合要求的内容date_new = '-'.join([year, month])dates.append(date_new)return datesexcept:print('数据获取失败!')
这个代码是用来获取网页中某一个城市目前所有时间,其返回结果如图:
之所以日期用这样的格式是因为该网站的url链接形式:
https://www.aqistudy.cn/historydata/daydata.php?city=北京&month=2020-07
他可以被分解为 base_url+city+month
其中,base_url = ‘https://www.aqistudy.cn/historydata/daydata.php?city=’
第二步:
在得到每个月份的url链接后,接下来就是爬取数据了,这里给大家分享一个函数,也是整个代码的 核心 -------- pandas.read_html()
这个函数专门是用来解决像表格型数据的获取的,百试百灵!
代码如下:
def spider(url):browser.get(url)df = pd.read_html(browser.page_source, header=0)[0] # 返回第一个Dataframetime.sleep(1)if not df.empty:# print(dfs)# df.to_csv('data.csv',mode='a',index=None)return dfelse:return spider(url) # 防止网络还没加载出来就爬取下一个url
整个代码也很简单,如果是仅仅获取到数据,并保存到csv文件的话,到这一步基本就结束了,只需要print一下即可,但是我这里是需要将获取到的数据保存到本地数据库中,并定时进行更新与维护![是不是觉得这都可以作为一个小项目写到简历里啦]
主体代码如下:
for ct in range(len(city)):list_data = []list_row = []for date in dates:url = base_url + city[ct] + '&month=' + datedf = spider(url)time.sleep(1)df['city'] = city[ct] # 添加一列for i in range(0, df.shape[0]): # 行for j in range(df.shape[1]): # 列data = df.iloc[i, j]list_row.append(data)list_data.append(list_row)list_row = []for n in range(len(list_data)):sql = 'insert ignore into aqidata (DATE,AQI,GRADE,PM25,PM10,SO2,CO,NO2,O3_8h,CITY)' \' VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)'x = cursor.execute(sql, (list_data[n][0], float(list_data[n][1]), list_data[n][2],float(list_data[n][3]),float(list_data[n][4]),float(list_data[n][5]),float(list_data[n][6]),float(list_data[n][7]),float(list_data[n][8]),list_data[n][9]))conn.commit()
cursor.close() # 关闭cursor
conn.close() # 关闭连接
browser.close()
上述代码可以实现全国各地每个时间段的数据的爬取与存储,只要你网站上有的数据我都可以爬下来,聪明的小伙伴根据这三块代码就可以实时的获取到全部数据啦!
注意:
如果想存储到数据库的话,需要提前建立数据库以及表(生怕你们跑代码出问题):
有了我这代码,还愁花钱买数据吗?根本不可能好吧!
彩蛋
彩蛋
(1)既然数据已经获取到啦,那么如何进行定时更新与维护呢?
其实可以参考我的这篇博客后半部分—>传送门
(2)既然污染物浓度数据都获取到了,有没有获取气象因子的数据方法呢?——— 有!
参考我的这篇博客----->传送门
综上就是这次博客讲解的全部内容,全部都是干货!如果对代码有疑惑或者不理解的地方,欢迎留言评论!如果觉得博客对你有帮助的话就点赞收藏吧!
如果需要完整数据的话,可以评论/私信我哈【有偿】
完整代码:
# coding=utf-8
from selenium import webdriver
import pymysql
import pandas as pd
import time
import requests
import re
from bs4 import BeautifulSoup
from sqlalchemy.exc import IntegrityErrordef get_date(url):response = requests.get(url)dates = []try:if response.status_code ==200:response = response.textsoup = BeautifulSoup(response, 'lxml')dates_ = soup.find_all('li')for i in dates_:if i.a: # 去除空值li = i.a.text # 提取li标签下的a标签date = re.findall('[0-9]*', li) # ['2019', '', '12', '', '']year = date[0]month = date[2]if month and year: # 去除不符合要求的内容date_new = '-'.join([year, month])dates.append(date_new)return datesexcept:print('数据获取失败!')
def spider(url):browser.get(url)df = pd.read_html(browser.page_source, header=0)[0] # 返回第一个Dataframetime.sleep(1.5)if not df.empty:# print(df)# df.to_csv('data.csv', mode='a', index=None)print(url+'数据爬取已完成')return dfelse:return spider(url) # 防止网络还没加载出来就爬取下一个url
if __name__ == '__main__':url = 'https://www.aqistudy.cn/historydata/monthdata.php?city=%E5%8C%97%E4%BA%AC'base_url = 'https://www.aqistudy.cn/historydata/daydata.php?city='# 声明浏览器对象option = webdriver.ChromeOptions()option.add_argument("start-maximized")option.add_argument("--disable-blink-features=AutomationControlled")option.add_experimental_option("excludeSwitches", ["enable-automation"])option.add_experimental_option("useAutomationExtension", False)browser = webdriver.Chrome(options=option)browser.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument",{'source':'''Object.defineProperty(navigator, 'webdriver', {get: () =>false'''})city = ['北京',]conn = pymysql.connect(host='localhost', user='root', db='weatherdata', passwd='12345678', charset='utf8') # 连接数据库cursor = conn.cursor() # 获取cursor游标dates = get_date(url)[1:]print(dates)list_data = []list_row = []for ct in range(len(city)):for date in dates:url = base_url + city[ct] + '&month=' + datedf = spider(url)# print(df)time.sleep(1.5)df['city'] = city[ct] # 添加一列for i in range(0, df.shape[0]): # 行for j in range(df.shape[1]): # 列data = df.iloc[i, j]list_row.append(data)list_data.append(list_row)list_row = []# print(list_data)for n in range(len(list_data)):sql = 'insert ignore into aqidata (DATE,AQI,GRADE,PM25,PM10,SO2,CO,NO2,O3_8h,CITY)' \' VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)'try:x = cursor.execute(sql, (list_data[n][0], float(list_data[n][1]), list_data[n][2],float(list_data[n][3]),float(list_data[n][4]),float(list_data[n][5]),float(list_data[n][6]),float(list_data[n][7]),float(list_data[n][8]),list_data[n][9]))except IntegrityError:print('IntegrityError happened!')conn.commit()cursor.close() # 关闭cursorconn.close() # 关闭连接browser.close()aqidata = pd.DataFrame(list_data,columns=['日期', 'AQI', '质量等级', 'PM2.5', 'PM10', 'SO2', 'CO', 'NO2', 'O3_8h', 'city'])print('所有数据爬取已完成!\n', aqidata)
python爬取中国空气质量在线监测平台分析数据【已更新】相关推荐
- 爬取中国空气质量在线监测分析平台
1.准备,爬取的链接地址 https://www.aqistudy.cn/html/city_detail.html 2.分析 a.当打开链接后,数据已经设置好了,说明里面大部分都是js通过ajax调 ...
- 中国空气质量在线监测分析平台-js混淆的坑
中国空气质量在线监测分析平台-js混淆的坑 一.背景 二.过程 1.确定加密参数 2.确定加密函数 3.处理js函数 三.总结 一.背景 分析过程参照:https://cuiqingcai.com/5 ...
- 中国空气质量在线监測分析平台
中国空气质量在线监測分析平台是公益性质的软件平台,提供PM2.5及天气数据的实时查询和历史数据可视化分析,统计挖掘,眼下收录了190个城市的PM2.5及天气信息数据,主要包含PM2.5实时查询.历史曲 ...
- python 爬取城市空气质量数据
[python]爬虫爬取中国城市的空气质量数据 使用工具:pycharm/python3.7,Chrome driver 使用库:selenium,time 一.下载Chrome driver(必读) ...
- python爬虫爬取(中国空气质量在线监测分析平台)北京PM2.5,2013年至2018年的数据
要爬取的数据网站如下图所示: 即是爬取该网站2013年12月2日至2018年11月份北京空气质量指数历史数据,其中要爬起的 内容如PM2.5,So2等,即是从这个网页内置的表格中爬取,因为该网站比较有 ...
- 爬取全国空气质量数据
思路: 1.空气质量在线监测平台 https://www.aqistudy.cn/: 2.分析网站,找到历史数据查询入口:https://www.aqistudy.cn/historydata/,首页 ...
- java获取空气质量在线监测分析平台(PM2.5真气网)数据
空气质量在线监测分析平台(PM2.5真气网) https://www.aqistudy.cn/ 获取实时监测数据: 通过以上信息可知请求需要携带的参数d是加密的,返回的信息也是加密的 查找getSer ...
- python中国最好大学排名_国内大学排名如何?用Python爬取中国大学排名
国内大学排名如何?用Python爬取中国大学排名准备阶段需要的库robots协议上代码代码框架*获取url信息*解析信息*输出数据*主函数结果 准备阶段 新手入门,不喜勿喷,这篇文章的内容其实也是在中 ...
- Python爬取中国知网文献、参考文献、引证文献
转载自博客园文章作为学习资料,代码及相关介绍非常详细.原文链接见Python爬取 中国知网文献.参考文献.引证文献
最新文章
- 每日一皮:前程序员离职后没人想接的代码...
- 安卓实训项目:基于储存卡音乐播放器实训报告5.0
- python 将YOLO(txt)格式的标注数据批量转换为PascalVOC(XML)格式的标注数据
- show processlist解析
- python设置字符间距_python字符串处理以及字符串格式化
- 单点登录终极方案之 CAS 应用及原理
- php中ajax用法,thinkphp中使用ajax
- Python批量提取Excel文件中的图片
- Ubuntu20.04更新源步骤
- MySQL数据以全量和增量方式,同步到ES搜索引擎
- c语言立体爱心会跳动,c语言编程实例——小球跳动
- Excel比较两列的值
- 用java观察者模式解耦经典三层架构
- mac下删除ntfs下的文件垃圾篓清空不干净的解决办法
- mysql 整除取整,MySQL小数位取整
- 样式和主题(Style and Theme)详解
- CAPL脚本中对Flexray事件的响应
- 高仿人人车 范围选择器
- 你对明星直播带货有多少误解?
- 《javascript语言精粹》读书笔记——函数
热门文章
- dependency一直报错,换各种jar包都不行
- 抓取得物数据出现验证码的解析思路
- 基于自定义gym环境的强化学习
- 华为软开面经(许愿OC)
- 审批流程 html,审批流程(标准)处理中.html
- Play 2.6 在Play中使用缓存
- Interval (mathematics)
- watermark知识点
- fprintf 函数详解
- Ubuntu 20.04安装CUDA失败导致系统黑屏消息nvidia 0000:01:00.0: can‘t change power state from D3cold to D0 的解决方法