爬取中国空气质量在线监测分析平台
1.准备,爬取的链接地址
https://www.aqistudy.cn/html/city_detail.html
2.分析
a.当打开链接后,数据已经设置好了,说明里面大部分都是js通过ajax调用的,
b.打开f12分析代码
通过捕获到的数据包,发现当前请求为ajax,携带着一个为d的参数且该请求携带的数据是加密过的,并且响应也是加密过的
c.这时候的问题就是我们不知道加密和解密是怎么完成的,如果不能解决这个问题,我们就无法继续进行。
解决思路:这里要使用火狐浏览器,火狐浏览器可以轻松看到放在html里面的javascript代码
d.放在谷歌里面,搜索方法
- 接着分析这两个方法getWeatherData内部的实现,该两个方法就在getData实现的下方。再进一步分析发现这两个方法都调用了 getServerData() 这个方法,并传递了 method、param 等参数,然后还有一个回调函数很明显是对返回数据进行处理的,这说明 Ajax 请求就是由这个 getServerData()方法发起
- 定位getServerData方法,查看其内部的具体实现。在谷歌浏览器中开启抓包工具,然后对该网站的首页https://www.aqistudy.cn/html/city_detail.html发起请求,捕获所有的数据包,然后在所有的数据包中实现全局搜索,搜索该方法是存在哪个文件中的。
- JavaScript 混淆:我们会惊讶的发现getServerData后面跟的是什么鬼啊?不符合js函数定义的写法呀!!!其实这里是经过 JavaScript 混淆加密了,混淆加密之后,代码将变为不可读的形式,但是功能是完全一致的,这是一种常见的 JavaScript 加密手段。我们想要查看到该方法的原始实现则必须对其进行反混淆。
- 反混淆:JavaScript 混淆之后,其实是有反混淆方法的,最简单的方法便是搜索在线反混淆网站,这里提供一个:http://www.bm8.com.cn/jsConfusion/。我们可以将getServerData存在的这行数据粘贴到反混淆的网站中。
将response里面的代码粘贴到反混淆里面就会得到正常的代码,只粘贴加密的那部分
- 分析:在反混淆后,我们很清晰的看到了ajax请求发送的实现。然后还看到了ajax对应post请求的动态加密请求参数的加密方法getParam(),并且将method和object作为了函数的参数。method和object是从getServerData函数的参数中获取的,那么getServerData函数中的method和object表示的是什么呢?我们需要回过头去查看getServerData函数的调用:
发现method是固定形式字符串,object就是param是一个字典,里面存储了三组键值对city表示查询城市名称,startTime和endTime为查询起止时间,type表示为HOUR:
至此getParam()函数中的两个参数的表示含义我们已经清楚了。getParam函数的返回值就是ajax对应post请求的动态加密请求参数了,我们需要定位到其函数内部的实现,看看是如何对请求参数进行加密的。在getServerData中我们发现了ajax请求对应的操作代码,其中还有一个非常重要的一步,就是ajax请求成功后的回调函数实现内部,接受到了响应数据data,data我们知道是一组密文数据,然后调用了decodeData对data进行了解密操作:
在反混淆网站的代码中我们可以搜索到getPrame和decodeData这两个函数的实现:
发现getParam函数中使用了 Base64 和 AES 对param进行加密。加密之后的字符串便作为ajax对应post的请求参数传送给服务器了。
服务器相应回来的密文数据是被decodeData进行解密的。观察解密函数发现是通过base64+AES+DES进行的解密!
- 总结:点击查询按钮后,最终是触发了getServerData函数发起了ajax请求,请求参数是通过getParam进行的加密,响应回来的密文数据是通过decodeData函数进行解密处理的。
- 接下来,我们需要借助于 PyExecJS 库来实现模拟JavaScript代码执行获取动态加密的请求参数,然后再将加密的响应数据带入decodeData进行解密即可!
- PyExecJS介绍:PyExecJS 是一个可以使用 Python 来模拟运行 JavaScript 的库。我们需要pip install PyExecJS对其进行环境安装。
- 开始执行js:
- 1.将反混淆网站中的代码粘贴到jsCode.js文件中
- 2.在该js文件中添加一个自定义函数getPostParamCode,该函数是为了获取且返回post请求的动态加密参数:
function getPostParamCode(method, city, type, startTime, endTime){var param = {};param.city = city;param.type = type;param.startTime = startTime;param.endTime = endTime;return getParam(method, param);
}
- 3.在py源文件中可以基于PyExecJS模拟执行步骤2中定义好的自定义函数,获取动态加密参数:
import execjsnode = execjs.get()# Params
method = 'GETCITYWEATHER'
city = '北京'
type = 'HOUR'
start_time = '2018-01-25 00:00:00'
end_time = '2018-01-25 23:00:00'# Compile javascript
file = 'jsCode.js'
ctx = node.compile(open(file).read())# Get params
js = 'getPostParamCode("{0}", "{1}", "{2}", "{3}", "{4}")'.format(method, city, type, start_time, end_time)
params = ctx.eval(js)
print(params)
- 4.接着我们用 requests 库来模拟 POST 请求:
import execjs
import requestsnode = execjs.get()# Params
method = 'GETCITYWEATHER'
city = '北京'
type = 'HOUR'
start_time = '2018-01-25 00:00:00'
end_time = '2018-01-25 23:00:00'# Compile javascript
file = 'jsCode.js'
ctx = node.compile(open(file).read())# Get params
js = 'getPostParamCode("{0}", "{1}", "{2}", "{3}", "{4}")'.format(method, city, type, start_time, end_time)
params = ctx.eval(js)#发起post请求
url = 'https://www.aqistudy.cn/apinew/aqistudyapi.php'
response_text = requests.post(url, data={'d': params}).text
print(response_text)
- 5.接下来我们再调用一下 JavaScript 中的 decodeData() 方法即可实现解密:
import execjs
import requestsnode = execjs.get()# Params
method = 'GETCITYWEATHER'
city = '北京'
type = 'HOUR'
start_time = '2018-01-25 00:00:00'
end_time = '2018-01-25 23:00:00'# Compile javascript
file = 'jsCode.js'
ctx = node.compile(open(file).read())# Get params
js = 'getPostParamCode("{0}", "{1}", "{2}", "{3}", "{4}")'.format(method, city, type, start_time, end_time)
params = ctx.eval(js)#发起post请求
url = 'https://www.aqistudy.cn/apinew/aqistudyapi.php'
response_text = requests.post(url, data={'d': params}).text#对加密的响应数据进行解密
js = 'decodeData("{0}")'.format(response_text)
decrypted_data = ctx.eval(js)
print(decrypted_data)
运行结果:
{"success":true,"errcode":0,"errmsg":"success","result":{"success":true,"data":{"total":24,"rows":[{"time":"2018-01-25 00:00:00","temp":"-7","humi":"35","wse":"1","wd":"\u4e1c\u5317\u98ce","tq":"\u6674"},{"time":"2018-01-25 01:00:00","temp":"-9","humi":"38","wse":"1","wd":"\u897f\u98ce","tq":"\u6674"},{"time":"2018-01-25 02:00:00","temp":"-10","humi":"40","wse":"1","wd":"\u4e1c\u5317\u98ce","tq":"\u6674"},{"time":"2018-01-25 03:00:00","temp":"-8","humi":"27","wse":"2","wd":"\u4e1c\u5317\u98ce","tq":"\u6674"},{"time":"2018-01-25 04:00:00","temp":"-8","humi":"26","wse":"2","wd":"\u4e1c\u98ce","tq":"\u6674"},{"time":"2018-01-25 05:00:00","temp":"-8","humi":"23","wse":"2","wd":"\u4e1c\u5317\u98ce","tq":"\u6674"},{"time":"2018-01-25 06:00:00","temp":"-9","humi":"27","wse":"2","wd":"\u4e1c\u5317\u98ce","tq":"\u591a\u4e91"},{"time":"2018-01-25 07:00:00","temp":"-9","humi":"24","wse":"2","wd":"\u4e1c\u5317\u98ce","tq":"\u591a\u4e91"},{"time":"2018-01-25 08:00:00","temp":"-9","humi":"25","wse":"2","wd":"\u4e1c\u98ce","tq":"\u6674\u8f6c\u591a\u4e91\u8f6c\u591a\u4e91\u95f4\u6674"},{"time":"2018-01-25 09:00:00","temp":"-8","humi":"21","wse":"3","wd":"\u4e1c\u5317\u98ce","tq":"\u6674\u8f6c\u591a\u4e91\u8f6c\u591a\u4e91\u95f4\u6674"},{"time":"2018-01-25 10:00:00","temp":"-7","humi":"19","wse":"3","wd":"\u4e1c\u5317\u98ce","tq":"\u6674\u8f6c\u591a\u4e91\u8f6c\u591a\u4e91\u95f4\u6674"},{"time":"2018-01-25 11:00:00","temp":"-6","humi":"18","wse":"3","wd":"\u4e1c\u5317\u98ce","tq":"\u591a\u4e91"},{"time":"2018-01-25 12:00:00","temp":"-6","humi":"17","wse":"3","wd":"\u4e1c\u5317\u98ce","tq":"\u591a\u4e91"},{"time":"2018-01-25 13:00:00","temp":"-5","humi":"17","wse":"2","wd":"\u4e1c\u5317\u98ce","tq":"\u591a\u4e91"},{"time":"2018-01-25 14:00:00","temp":"-5","humi":"16","wse":"2","wd":"\u4e1c\u98ce","tq":"\u591a\u4e91"},{"time":"2018-01-25 15:00:00","temp":"-5","humi":"15","wse":"2","wd":"\u5317\u98ce","tq":"\u591a\u4e91"},{"time":"2018-01-25 16:00:00","temp":"-5","humi":"16","wse":"2","wd":"\u4e1c\u5317\u98ce","tq":"\u591a\u4e91"},{"time":"2018-01-25 17:00:00","temp":"-5","humi":"16","wse":"2","wd":"\u4e1c\u98ce","tq":"\u591a\u4e91"},{"time":"2018-01-25 18:00:00","temp":"-6","humi":"18","wse":"2","wd":"\u4e1c\u98ce","tq":"\u6674\u95f4\u591a\u4e91"},{"time":"2018-01-25 19:00:00","temp":"-7","humi":"19","wse":"2","wd":"\u4e1c\u98ce","tq":"\u6674\u95f4\u591a\u4e91"},{"time":"2018-01-25 20:00:00","temp":"-7","humi":"19","wse":"1","wd":"\u4e1c\u98ce","tq":"\u6674\u95f4\u591a\u4e91"},{"time":"2018-01-25 21:00:00","temp":"-7","humi":"19","wse":"0","wd":"\u5357\u98ce","tq":"\u6674\u95f4\u591a\u4e91"},{"time":"2018-01-25 22:00:00","temp":"-7","humi":"22","wse":"1","wd":"\u4e1c\u5317\u98ce","tq":"\u6674\u95f4\u591a\u4e91"},{"time":"2018-01-25 23:00:00","temp":"-9","humi":"27","wse":"1","wd":"\u897f\u5357\u98ce","tq":"\u6674\u95f4\u591a\u4e91"}]}}}
复制代码
爬取中国空气质量在线监测分析平台相关推荐
- 中国空气质量在线监测分析平台-js混淆的坑
中国空气质量在线监测分析平台-js混淆的坑 一.背景 二.过程 1.确定加密参数 2.确定加密函数 3.处理js函数 三.总结 一.背景 分析过程参照:https://cuiqingcai.com/5 ...
- python爬取中国空气质量在线监测平台分析数据【已更新】
**本文介绍如何爬取诸如北京等城市的空气污染物浓度数据,并附有完整代码,统统解决你们找不到数据的科研问题!干货满满!!! 2021年1月12日更新 看了很多小伙伴的评论,发现我的代码被官方给" ...
- python爬虫爬取(中国空气质量在线监测分析平台)北京PM2.5,2013年至2018年的数据
要爬取的数据网站如下图所示: 即是爬取该网站2013年12月2日至2018年11月份北京空气质量指数历史数据,其中要爬起的 内容如PM2.5,So2等,即是从这个网页内置的表格中爬取,因为该网站比较有 ...
- java获取空气质量在线监测分析平台(PM2.5真气网)数据
空气质量在线监测分析平台(PM2.5真气网) https://www.aqistudy.cn/ 获取实时监测数据: 通过以上信息可知请求需要携带的参数d是加密的,返回的信息也是加密的 查找getSer ...
- 中国空气质量在线监測分析平台
中国空气质量在线监測分析平台是公益性质的软件平台,提供PM2.5及天气数据的实时查询和历史数据可视化分析,统计挖掘,眼下收录了190个城市的PM2.5及天气信息数据,主要包含PM2.5实时查询.历史曲 ...
- 爬取全国空气质量数据
思路: 1.空气质量在线监测平台 https://www.aqistudy.cn/: 2.分析网站,找到历史数据查询入口:https://www.aqistudy.cn/historydata/,首页 ...
- 环保数采仪助力空气质量在线监测系统
空气的质量和人民生活健康息息相关.目前,空气污染源影响空气质量的最主要因素之一是来自固定和流动污染源的人为污染物排放,包括车辆.船舶.飞机的尾气.工业污染.居民生活和取暖.垃圾焚烧等. 随着生活水平的 ...
- python 爬取城市空气质量数据
[python]爬虫爬取中国城市的空气质量数据 使用工具:pycharm/python3.7,Chrome driver 使用库:selenium,time 一.下载Chrome driver(必读) ...
- python爬取空气质量_python爬取全国空气质量信息
主要模块 requests模块.使用requests模块来获取http响应 gevent模块.使用gevent开启多个协程,加快爬取速度 re模块或beautifulsoup模块.正则表达式解析与be ...
最新文章
- ISME:二氧化碳和氮水平对植物根表菌群和功能的影响
- 模拟信号与离散信号之间的频率关系(由模拟信号采样得到的离散信号)
- 详解模板注入漏洞(下)
- Apache Hadoop 2.4.1 单节点安装
- WinCE启动失败的原因与解决办法分析
- Android(Java):jni源代码
- 19年8月 字母哥 第三章 spring boot 配置原理实战 用热点公司网不行
- [CodeForces-1138B] *Circus 解方程|数学
- PyTorch 入坑十一: 损失函数、正则化----深刻剖析softmax+CrossEntropyLoss
- HTTP Get与Post的区别
- android studio for android learning (十) android之activity的启动和关闭
- Qt 启动应用程序的3种方式
- MySQL数据库如何建立视图
- HTTP消息推送原理
- 桌面美化 | win10高仿mac桌面
- 非常好用的节假日查询接口
- Matching the Blanks: Distributional Similarity for Relation Learning (通篇翻译)
- 如何预防 CSRF 攻击?
- 全新 MacBook Air MGN63CH/A / MGN93CH/A / MGND3CH/A / MGN73CH/A / MGNA3CH / MGNE3CH/A 配置报价图片
- 深交所a股证券代码_深交所股票代码000001
热门文章
- 使用Spark中DataFrame的语法与SQL操作,对人类数据进行处理,比较学历与离婚率的关系
- 高精度地图中的中英文专业词汇对照
- 中国大学MOOC C语言程序设计(大连理工大学) 课后编程题 第十二周题解(个人向仅供参考)
- Marquee属性详解
- python ipo模式包括什么_什么是IPO?
- windows 安装chatterbot
- js 前端常用时间操作:时间戳、当前时间
- 浅析Content Negotation在Nancy的实现和使用
- Allegro ---检查Dummy Net 、Not a net和有命名但是其中一端未连接的网络
- SSM (JDK 1.7) 使用Rabbit MQ