Python爬虫天气预报实例详解(小白入门)


Posted in Python onJanuary 24, 2018

本文研究的主要是Python爬虫天气预报的相关内容,具体介绍如下。

这次要爬的站点是这个:http://www.weather.com.cn/forecast/

要求是把你所在城市过去一年的历史数据爬出来。

分析网站

首先来到目标数据的网页 http://www.weather.com.cn/weather40d/101280701.shtml

Python爬虫天气预报实例详解(小白入门)

我们可以看到,我们需要的天气数据都是放在图表上的,在切换月份的时候,发现只有部分页面刷新了,就是天气数据的那块,而URL没有变化。

这是因为网页前端使用了JS异步加载的技术,更新时不用加载整个页面,从而提升了网页的加载速度。

对于这种非静态页面,我们在请求数据时,就不能简单的通过替换URL来请求不同的页面。

着眼点要放在Network,观察整个请求的过程,从中寻找突破口。

老规矩按下F12 > network,切换下页面,发现多了一些东西,这就是切换月份,浏览器发出的请求,可以很清楚的看到请求头和请求参数。

Python爬虫天气预报实例详解(小白入门)

再来看看Response是怎样的吧

Python爬虫天气预报实例详解(小白入门)

真是没想到,返回的居然是json格式的天气数据!直接做 json 反序化就能变成字典的形式,省掉了我们解析 html 的麻烦呀。既然找到了数据所在的地方,就可以开始尝试构建请求了。

构建请求

先直接copy上面的Request URL,试下请求。http://d1.weather.com.cn/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的魅力吧。

subkey = {'date', 'hmax', 'hmin', 'hgl', 'fe', 'wk', 'time'}
subdict = {key: dict[key] for key in subkey}

然后我还做了个用中文替换的原来key的功能,只需要稍作修改,for in 取出来的是键值对,然后用中文的value,替换英文的key,就ok了。

subkey = {'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爬虫天气预报实例详解(小白入门)

Python的代码非常短才30多行,就完成了爬虫的整个流程, 请求,解析,保存,一气呵成,可谓是爬虫界的豪杰。

# encoding=utf-8
import requests
import json
import pymongo
import time

def request(year, month):
  url = "http://d1.weather.com.cn/calendar_new/" + 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": "http://www.weather.com.cn/weather40d/101280701.shtml",
  }
  return requests.get(url, headers=headers)

def parse(res):
  json_str = res.content.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 > 9 else "0" + str(i)   #小于10的月份要补0
    save(parse(request(year, month)))

time.sleep(1)

总结

以上就是本文关于Python爬虫天气预报实例详解(小白入门)的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

Python 相关文章推荐
推荐11个实用Python库
Jan 23 Python
Python中的赋值、浅拷贝、深拷贝介绍
Mar 09 Python
python 除法保留两位小数点的方法
Jul 16 Python
详解Django+Uwsgi+Nginx 实现生产环境部署
Nov 06 Python
python实现windows壁纸定期更换功能
Jan 21 Python
PyQt5实现简单数据标注工具
Mar 18 Python
Python实现查找字符串数组最长公共前缀示例
Mar 27 Python
Python利用WMI实现ping命令的例子
Aug 14 Python
Python字符串格式化输出代码实例
Nov 22 Python
Python Pandas 转换unix时间戳方式
Dec 07 Python
TensorFlow2.1.0安装过程中setuptools、wrapt等相关错误指南
Apr 08 Python
如何在windows下安装配置python工具Ulipad
Oct 27 Python
Python实现PS滤镜碎片特效功能示例
Jan 24 #Python
python的re正则表达式实例代码
Jan 24 #Python
python实现生命游戏的示例代码(Game of Life)
Jan 24 #Python
Python 获得命令行参数的方法(推荐)
Jan 24 #Python
Python实现的rsa加密算法详解
Jan 24 #Python
利用Python+Java调用Shell脚本时的死锁陷阱详解
Jan 24 #Python
python做量化投资系列之比特币初始配置
Jan 23 #Python
You might like
php生成图形验证码几种方法小结
2013/08/15 PHP
ThinkPHP CURD方法之table方法详解
2014/06/18 PHP
Codeigniter框架的更新事务(transaction)BUG及解决方法
2014/07/25 PHP
js 操作css实现代码
2009/06/11 Javascript
手机端网页点击链接触发自动拨打或保存电话的示例代码
2014/08/15 Javascript
js面向对象之静态方法和静态属性实例分析
2015/01/10 Javascript
在JavaScript中操作时间之getMonth()方法的使用
2015/06/10 Javascript
jquery实现带渐变淡入淡出并向右依次展开的多级菜单效果实例
2015/08/22 Javascript
jQuery实现背景弹性滚动的导航效果
2016/06/01 Javascript
jQuery实现的兼容性浮动层示例
2016/08/02 Javascript
js 输入框 正则表达式(菜鸟必看教程)
2017/02/19 Javascript
Angular JS 生成动态二维码的方法
2017/02/23 Javascript
详解实现一个通用的“划词高亮”在线笔记功能
2019/04/23 Javascript
vue 获取视频时长的实例代码
2019/08/20 Javascript
[46:43]DOTA2上海特级锦标赛D组小组赛#1 EG VS COL第三局
2016/02/28 DOTA
[01:05:07]DOTA2-DPC中国联赛 正赛 DLG vs Dragon BO3 第一场2月1日
2021/03/11 DOTA
Python中统计函数运行耗时的方法
2015/05/05 Python
详解如何管理多个Python版本和虚拟环境
2019/05/10 Python
python 判断三个数字中的最大值实例代码
2019/07/24 Python
python制作朋友圈九宫格图片
2019/11/03 Python
python 定义类时,实现内部方法的互相调用
2019/12/25 Python
PyTorch加载预训练模型实例(pretrained)
2020/01/17 Python
Python pymsql模块的使用
2020/09/07 Python
Python导入父文件夹中模块并读取当前文件夹内的资源
2020/11/19 Python
python 实现图片批量压缩的示例
2020/12/18 Python
大韩航空官方网站:Korean Air
2017/10/25 全球购物
Bench加拿大官方网站:英国城市服装品牌
2017/11/03 全球购物
zooplus波兰:在线宠物店
2019/07/21 全球购物
顶岗实习接收函
2014/01/09 职场文书
大一工商管理职业生涯规划:有梦最美,行动相随
2014/09/18 职场文书
优秀共青团员事迹材料
2014/12/25 职场文书
消防宣传标语大全
2015/08/03 职场文书
初中化学教学反思
2016/02/22 职场文书
高效课堂教学反思
2016/02/24 职场文书
Python极值整数的边界探讨分析
2021/09/15 Python
详解SQL的窗口函数
2022/04/21 Oracle