百年软件后台管理系统Python爬⾍天⽓预报实例详解(⼩⽩⼊门)
本⽂研究的主要是Python爬⾍天⽓预报的相关内容,具体介绍如下。
这次要爬的站点是这个:
要求是把你所在城市过去⼀年的历史数据爬出来。
分析⽹站
编程猫打地鼠教程
⾸先来到⽬标数据的⽹页
我们可以看到,我们需要的天⽓数据都是放在图表上的,在切换⽉份的时候,发现只有部分页⾯刷新了,就是天⽓数据的那块,⽽URL没有变化。
这是因为⽹页前端使⽤了JS异步加载的技术,更新时不⽤加载整个页⾯,从⽽提升了⽹页的加载速度。
对于这种⾮静态页⾯,我们在请求数据时,就不能简单的通过替换URL来请求不同的页⾯。
着眼点要放在Network,观察整个请求的过程,从中寻突破⼝。
⽼规矩按下F12 > network,切换下页⾯,发现多了⼀些东西,这就是切换⽉份,浏览器发出的请求,可以很清楚的看到请求头和请求参数。
再来看看Response是怎样的吧
真是没想到,返回的居然是json格式的天⽓数据!直接做 json 反序化就能变成字典的形式,省掉了我们解析 html 的⿇烦呀。既然到了数据所在的地⽅,就可以开始尝试构建请求了。
构建请求
先直接copy上⾯的Request URL,试下请求。d1.weather/calendar_new/2017/101280701_201706.html?
颜查询器_=1495720234075
然后发现报错了,先把请求头全部满上怼进去,发现可以正常的响应。
但是我们还要分析下到底哪个参数不对出了问题。经过尝试,发现请求头⾥的Referer的原因,去掉就会报错。
这是因为这是浏览器发出请求时,会通过Referer告诉服务器我是从哪个页⾯链接过来的,有些⽹站会对这个做验证,主要时为了防⽌别⼈盗链的问题。
这个中国天⽓⽹,就是验证了Referer⾥的域名是不是⾃⼰的,不是的话就会403禁⽌访问服务器。
接下来就要考虑怎么请求不同⽉份的数据。
通过观察URL,发现其实很简单,直接替换年⽉,就可以循环抓取,得到整年的数据。
那中间的101280701是什么意思呢,经过请求不同的城市对⽐URL,我发现这是表⽰地理位置的⼀个数据。
前3位表⽰国家中国,后6位依次表⽰,省份,城市和区县。修改这⾥,就能实现对不同城市进⾏查询了。
最后⼀个参数1495720234075,开始以为是随机数,后来有朋友提醒这是unix时间戳,实际上就算去掉这个,也能正常访问数据,没什么影响。
解析数据
拿到数据以后,就可以开始解析了。不过这⾥根本⽤不上xpath,直接⽤Json.load(),就能反序列化成json对象,从中取出字典,节省很多⿇烦。需要注意的是,返回的40天的天⽓数据 fc40 字符串是这样
var fc40 = [{"blue":"","c1":"","c2":"","cla":"history","date":"20151227","des":"历史均值","fe":"","hgl":"17%","hmax":"17","hmin":"13","hol":"","jq":""
.....]}
前⾯的字符串需要去掉,才能反序列化,注意这⾥的json对象实际是个存储字典的list[]。开始想⽤正则,不过不熟没弄好。后来发现python 字符串也能使⽤这样的语法 [a:b] 来取出位置a到位置b的字符串,所以就直接⽤[11 : ], 就能取出fc40 后⾯的字符串,也很⽅便。
保存数据
因为数据量⽐较⼤,就采⽤mongodb来做数据持久化。mongodb 我也是才学习,参考了别⼈的教程,才做好了环境配置,过程打算总结到另⼀篇,这⾥就打算不多说了。
因为原本的放了天⽓数据的字典⾥⾯有太多没⽤的数据,我只想提取出我想要的部分,就⽤了⼀个⼩技巧。
将想要的数据的key,保存成subkey这个字典,⽤ for in取出subkey中的key,再回到原本的dict中取出对应的值,最后将这些键值对,都存储在⼀个subdict字典⾥,就完成了提取出⼦字典的功能。说起来很⿇烦,但是代码却很简单,这可能就是python的魅⼒吧。
安卓手机如何打开jar文件
1 2subkey ={'date', 'hmax', 'hmin', 'hgl', 'fe', 'wk', 'time'} subdict ={key: dict[key] for key in subkey}
然后我还做了个⽤中⽂替换的原来key的功能,只需要稍作修改,for in 取出来的是键值对,然后⽤中⽂的value,替换英⽂的key,就ok 了。python请求并解析json数据
1 2 3subkey ={'date': '⽇期', 'hmax': '最⾼温度', 'hmin': '最低温度', 'hgl': '降⽔概率', 'fe': '节⽇', 'wk': '星期'}
subdict ={value: dict[key] for key, value in subkey.items()}
最后的结果如下图,这是⽤pycharm上的mongodb可视化插件Mongo Plugin看到的,在pycharm>settings>plugins⾥⾯可以搜索安装。需要注意的是,默认只显⽰300条数据。想要看到更多,就在Row limit 上输⼊总数就⾏。
Python的代码⾮常短才30多⾏,就完成了爬⾍的整个流程, 请求,解析,保存,⼀⽓呵成,可谓是爬⾍界的豪杰
# encoding=utf-8
import requests
import json
import pymongo
import time
def request(year, month):
url =""+year +"/101280701_"+year +month +".html?_=1495685758174"
headers ={
怎么编写一个简单的小程序"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102
Safari/537.36",
"Referer": "",
}
(url, headers=headers)
def parse(res):
json_str =t.decode(encoding='utf-8')[11:]
return json.loads(json_str)
def save(list):
subkey ={'date': '⽇期', 'hmax': '最⾼温度', 'hmin': '最低温度', 'hgl': '降⽔概率', 'fe': '节⽇', 'wk': '星期', 'time': '发布时间'}
for dict in list:
subdict ={value: dict[key] for key, value in subkey.items()}  #提取原字典中部分键值对,并替换key为中⽂
forecast.insert_one(subdict)                  #插⼊mongodb数据库
if__name__ =='__main__':
year ="2016"
month =1
client =pymongo.MongoClient('localhost', 27017)  # 连接mongodb,端⼝27017
test =client['test']              # 创建数据库⽂件test
forecast =test['forecast']            # 创建表forecast
for i in range(month, 13):
month =str(i) if i > 9else"0"+str(i)  #⼩于10的⽉份要补0 save(parse(request(year, month)))

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。