python爬取天气后报网
前言
大二下学期的大数据技术导论课上由于需要获取数据进行分析,我决定学习python爬虫来获取数据。由于对于数据需求量相对较大,我最终选择爬取
天气后报网,该网站可以查询到全国各地多年的数据,而且相对容易爬取。
需求分析:
(1)需要得到全国各大城市的历史天气数据集。
(2)每条天气信息应该包含的内容包括城市名、日期、温度、天气、风向。
(3)以城市名分类,按日期存储在可读的文件中。
(4)存储信息类型应该为字符型。
整体解决方案:
第一步:选择适合进行信息爬虫的网页。
第二步:对该网页相关信息所在的url进行获取。
第三步:通过解析url对应的网页获取信息并存储。
详细解决方案:
第一步:选择适合进行信息爬虫的网页。
(1)由于要获取的是历史天气信息,我们不考虑常见的天气预报网页,最后选择了“天气后报网”作为目标网站。如下图,该网站天气信息按条分布,符合我们的爬虫需求。

(2)我们查看了该网站的robots协议,通过输入相关网址,我们没有找到robots.txt的相关文件,说明该网站允许任何形式的网页爬虫。
(3)我们查看了该类网页的源代码,如下图所示,发现其标签较为清晰,不存在信息存储混乱情况,便于爬取。

第二步:对该网页相关信息所在的url进行获取。
(1)对网页的目录要清晰的解析
为了爬取到全年各地各个月份每一天的所有天气信息,我们小组首先先对网页的层次进行解析,发现网站大体可以分为三层,第一层是地名的链接,通向各个地名的月份链接页面,第二层是月份链接,对应各个网页具体天数,第三个层次则是具体每一天的天气信息,与是我们本着分而治之的原则,对应不同网页的不同层次依次解析对应的网页以获取我们想要的信息。


天气后报网的第一层层次-地名链接

天气后报网第二层次-时间链接

天气后报第三层次具体时间的信息
(1)解析地名网页层次结构-获取地名链接

第一个层次的网页代码
进过观察第一个层次的网页代码,我们发现我们要提取的地名链接在class=”citychk”的div标签的子孙节点<a>标签的href的属性中,于是我们调用beutifulsoup库的findall()方法将a标签以及它的内容放到一个集合中,依次遍历将对应的链接写道web_link.txt文件中。

解析地名链接的核心代码

成功爬取的第一部分地名的链接
(2)解析地名网页层次结构-获取月份链接

进过我们观察发现,我们想要的月份链接存储在class=”box_pcity”的div标签下的li内的a标签的href属性内,于是我们采用同样的方法,依次遍历提取我们想要的月份链接,并按照不同的地名,保存在对应地名的文件中。
第三步:通过解析url对应的网页获取信息并存储。
(1)设置请求登录网页功能,根据不同的url按址访问网页,若请求不成功,抛出HTTPError异常。
(2)设置获取数据功能,按照网页源代码中的标签,设置遍历规则,获取每条数据。注意设置“encoding=‘gb18030’”,改变标准输出的默认编码, 防止控制台打印乱码。
(3)设置文件存储功能,将爬取的数据按年份和月份分类,分别存储在不同的CSV文件中。注意文件名的设置为城市名加日期,方便后期整理。
4. 程序流程图

5. 运行测试截图
(1)url获取



(2)解析网页



附录代码:
爬虫部分代码
-------------------------------------------------------
get_all_city_info.py文件是为了获取每个地方按照月份的链接的代码
get_city_weather_link.py是为了获取地名连接的代码
get_city_weather_content.py是为了获取具体信息的代码
get_all_city_info.py
import urllib.request
import urllib.parse
from bs4 import BeautifulSoup
import os def get_city_link():#将读取到的文件转化为字典
web_link={}
f=open('web_link.txt')
line=f.readline()
while line:
split_line=line.split(',')
key=split_line[0]
value=split_line[1]
value=value.replace('\n','')
web_link[key]=value
line=f.readline() f.close()
return web_link def get_place_name(web_link):#得到所有的地名
place=[]
for key in web_link:
place.append(key)
return place def get_html(url):#依次访问这些网站得到这些网站的html代码
header = {
'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)'
}
# 伪装浏览器
request = urllib.request.Request(url, headers=header)
response = urllib.request.urlopen(request)
html = response.read()
soup=BeautifulSoup(html,'html.parser')
pretty_html=soup.prettify()
return pretty_html def resolve_html(html,city):
dict={}
soup=BeautifulSoup(html,'html.parser')
for div in soup.find_all('div',class_='box pcity'):
for a in div.find_all('a'):
new_time=''
link='http://www.tianqihoubao.com'+a.attrs['href']
time=str(a.string)
for i in range(len(time)):
if time[i]!=' ' and time[i]!='\n':
new_time=new_time+time[i]
if time.find(city)>=0:
dict[new_time]=link
return dict def trans_dict_to_file(dict,city,file_path):#将爬取到的网址依次存放到文件中
file_path=file_path+city+'.txt'
for key in dict:
with open(file_path,'a') as f:
f.write(key+','+dict[key]+'\n') def main():
path='D:\\face\weatherspider\\time_link\\' web_link=get_city_link()
citys=get_place_name(web_link)
count=0
for city in citys:
try:
count=count+1
print("正在抓取第%d个页面..."%(count))
html=get_html(web_link[city])#获取该城市的页面
print("抓取第%d个页面成功!"%(count))
keyword=city+'天气'
print('正在解析%d个网页...'%(count))
dict=resolve_html(html,keyword)
trans_dict_to_file(dict,city,path)
print('解析第%d个网页成功!'%(count))
except:
continue main()
get_city_weather_content.py
# coding=utf-8
import io
import sys
import requests
from bs4 import BeautifulSoup
import numpy as np
import pandas as pd
import csv
import time
import urllib sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='gb18030') # 改变标准输出的默认编码, 防止控制台打印乱码 def get_soup(year, month):
url = 'http://www.tianqihoubao.com/lishi/' + 'changzhou/' + 'month' + '/' + str(year) + str(month) + '.html'
try:
r = requests.get(url, timeout=30)
r.raise_for_status() # 若请求不成功,抛出HTTPError 异常
# r.encoding = 'gbk'
soup = BeautifulSoup(r.text, 'lxml')
return soup
except HTTPError:
return "Request Error" def saveTocsv(data, fileName):
'''
将天气数据保存至csv文件
'''
result_weather = pd.DataFrame(data, columns=['date', 'tq', 'temp', 'wind'])
result_weather.to_csv(fileName, index=False, encoding='gbk')
print('Save all weather success!') def get_data():
soup = get_soup(year, month)
all_weather = soup.find('div', class_="wdetail").find('table').find_all("tr")
data = list()
for tr in all_weather[1:]:
td_li = tr.find_all("td")
for td in td_li:
s = td.get_text()
data.append("".join(s.split())) res = np.array(data).reshape(-1, 4)
return res if __name__ == '__main__':
years = ['','','','','','','','','']
months = ['','','','','','','','','','','',''] for year in years:
for month in months:
data = get_data()
saveTocsv(data, '常州'+str(year)+str(month)+'.csv')
get_city_weather_link.py
import urllib.request
import urllib.parse
from bs4 import BeautifulSoup def get_html(url):
header = {
'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)'
}
# 伪装浏览器
request = urllib.request.Request(url, headers=header)
response = urllib.request.urlopen(request)
html = response.read()
return html def main():
url = 'http://www.tianqihoubao.com/lishi/index.htm'
html = get_html(url)
pretty_html=parse_home_page(html)
get_city_link(pretty_html) def parse_home_page(html):
#将网页熬成一锅汤
soup=BeautifulSoup(html,'html.parser')
pretty_html=soup.prettify()
return pretty_html def get_city_link(html):
website={}
url='http://www.tianqihoubao.com'
soup=BeautifulSoup(html,'html.parser')
div_city=soup.find_all('div',class_='citychk')
city_html=str(div_city[0])
city_soup=BeautifulSoup(city_html,'html.parser')
for k in city_soup.find_all('a'):
index=return_index(k['title'])
place=k['title'][0:index]
website[place]=url+k['href']
for key in website:#将各地天气链接存到文件中
with open('web_link.txt','a') as f:
f.write(key+','+website[key]+'\n') def return_index(s):
for i in range(len(s)):
if s[i]=='历':
break
return i main()
python爬取天气后报网的更多相关文章
- 毕设之Python爬取天气数据及可视化分析
写在前面的一些P话:(https://jq.qq.com/?_wv=1027&k=RFkfeU8j) 天气预报我们每天都会关注,我们可以根据未来的天气增减衣物.安排出行,每天的气温.风速风向. ...
- (python爬取小故事网并写入mysql)
前言: 这是一篇来自整理EVERNOTE的笔记所产生的小博客,实现功能主要为用广度优先算法爬取小故事网,爬满100个链接并写入mysql,虽然CS作为双学位已经修习了三年多了,但不仅理论知识一般,动手 ...
- Python爬取中国票房网所有电影片名和演员名字,爬取齐鲁网大陆所有电视剧名称
爬取CBO中国票房网所有电影片名和演员名字 # -*- coding: utf-8 -*- # 爬取CBO中国票房网所有电影片名 import json import requests import ...
- python爬取斗图网中的 “最新套图”和“最新表情”
1.分析斗图网 斗图网地址:http://www.doutula.com 网站的顶部有这两个部分: 先分析“最新套图” 发现地址栏变成了这个链接,我们在点击第二页 可见,每一页的地址栏只有后面的pag ...
- 适合初学者的Python爬取链家网教程
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: TinaLY PS:如有需要Python学习资料的小伙伴可以加点击下 ...
- Python 爬取煎蛋网妹子图片
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Date : 2017-08-24 10:17:28 # @Author : EnderZhou (z ...
- python爬取中国知网部分论文信息
爬取指定主题的论文,并以相关度排序. #!/usr/bin/python3 # -*- coding: utf-8 -*- import requests import linecache impor ...
- python爬取千库网
url:https://i588ku.com/beijing/0-0-default-0-8-0-0-0-0-1/ 有水印 但是点进去就没了 这里先来测试是否有反爬虫 import requests ...
- Python爬取猪肉价格网并获取Json数据
场景 猪肉价格网站: http://zhujia.zhuwang.cc/ 注: 博客: https://blog.csdn.net/badao_liumang_qizhi 关注公众号 霸道的程序猿 获 ...
随机推荐
- docker安装mysql5.6和redis3.2
环境:centos 6.8, docker version 1.7.1 1.docker安装mysql5.6 第一步:拉取镜像 docker pull mysql:5.6 第二步:docker run ...
- IE浏览器如何实现断点续传
需求: 支持大文件批量上传(20G)和下载,同时需要保证上传期间用户电脑不出现卡死等体验: 内网百兆网络上传速度为12MB/S 服务器内存占用低 支持文件夹上传,文件夹中的文件数量达到1万个以上,且包 ...
- TTTTTTTTTTTTTTTTTTT CF 银行转账 图论 智商题
C. Money Transfers time limit per test 1 second memory limit per test 256 megabytes input standard i ...
- TTTTTTTTTTTT CF 653D 送邮递员
链接:给一张n个点m条带权边的有向图,有x个人从起点出发到终点,每个人带的都带相同重量的货物, 规定一条边最多能经过其上权的重量的货物,问最多能带多重的货物? 2 ≤ n ≤ 50, 1 ≤ m ≤ ...
- 八、定制new和delete
条款49:了解new-handler的行为 new异常会发生什么事? 在旧式的编译器中,operator new分配内存失败的时候,会返回一个null指针.而现在则是会抛出一个异常. 而在抛出这个异常 ...
- cursor url 自定义鼠标样式
cursor可以自定义鼠标,写法是cursor:url(“图片路径”),pointer; url:需使用的自定义光标的 URL.图片类型需要是.cur或.ani和jpg,png等格式的(.cur或.a ...
- C++入门经典-例2.4-使用scanf格式输入函数得到用户输入的数据
1:puts函数可以输出提示信息的字符串. 2:代码如下: // 2.4.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" int main( ...
- LeetCode124----二叉树中最大路径和
给定一个非空二叉树,返回其最大路径和. 本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列.该路径至少包含一个节点,且不需要经过根节点. 示例 1: 输入: [1,2,3] 1 / \ 2 ...
- sudo密码一直出错
Linux默认是没有将用户添加到sudoers列表中的,需要root手动将账户添加到sudoers列表中,才能让普通账户执行sudo命令. 所以要将用户添加到sudoers组中,才能执行sudo命令, ...
- [NLP] 语义网络与知识图谱入门(二)
语义网络与知识图谱入门(二) OWL 本体声明 owl用owl:Ontology来声明一个本体.rdf:about属性为本体提供一个名称或引用.根据标准,当rdf:about属性的值为"&q ...