爬取全国各城市当天天气信息
准备工作
- 网页地址:http://www.weather.com.cn/textFC/hb.shtml
-
打开页面后发现要爬取的内容是在表格内,如下图所示,我们需要省份、城市名称,最高气温和最低气温。
*在“北京”上右键--检查(不要在空白处)
准备工作小结
- 要爬取的内容全部是在div标签class="conMidtab"内
- 要爬取的每个省份数据分别在各个table标签内
- 要爬取的每个城市数据分别在各个tr标签内(从第3个起,最后一页除外)
- 要爬取的城市名称是在第2个td标签内
- 要爬取的最高气温是在第5个td标签内
- 要爬取的最低气温是在倒数第2个td标签内
代码思路
- 先向一个网址发起请求,获取数据,成功后再考虑遍历所的的网址。
- 利用bs4分析上一步获取到的数据,拿到各城市名称,最高气温和最低气温
- 将城市名称,最高气温和最低气温转换成字典
- 将字典写入csv
第7期整理的代码(基础较差,花了几天时间才弄明白)
import requests
import csv
from bs4 import BeautifulSoup
def web_resquest(url):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36'
}
response = requests.get(url, headers=headers)
text = response.content.decode('utf-8')
return text
def web_parse(text):
list_1 = []
# soup = BeautifulSoup(text, 'lxml') #最后一页标签不全就出现错误了
# 'html5lib'可以解决标签不全的问题,注意先安装才能使用 pip install html5lib
soup = BeautifulSoup(text, 'html5lib') # 将网页请求得到的结果,返回一个soup对象
# 先找到所有表的信息 div class_='conMidtab' 注间有个下划线
conMidtab = soup.find('div', class_='conMidtab') # 获取表间部分,简单理解是只留下需要部分用来解析
# print(conMidtab)
# 接下来找每一个 直辖市或者省会的 table标签
tables = conMidtab.find_all('table')
for table in tables:
# print(table)
# print("*" * 80)
# 找table标签里面的tr标签 (来个切片把前2个过滤掉) province
trs = table.find_all("tr")[2:]
# enumerate()这个方法 返回2个值 一个是值另一个是这个值所对应的索引
for index, tr in enumerate(trs):
info = {} # 建个空字典
# print(tr)
# print(index)
# print("#" * 80)
tds = tr.find_all("td")
# for td in tds:
# print(td)
# print("#"*90)
# kity = tds[0].stripped_strings # 换行取城市名称,返回的是一个迭代器
kity_td = tds[0] # 城市标签
kity = list(tds[0].stripped_strings)[0] # 换成列表取数据,便可获取城市名称
# 进入下一个省份时,第一个是省份,第二个才是城市,有时省份和城市同名
# 每次进入一下个省份时都多一个td标签,退多了省份的标签,正好可获取省份名称
if index == 0:
province = list(tds[0].stripped_strings)[0] # 获取省份名称
kity_td = tds[1] # 城市标签
kity = list(tds[1].stripped_strings)[0] # 换成列表取数据,便可获取城市名称
# 同样的方法获取最高气温和最低气温,利用倒数方法就不用判断顺序
max_temp_td = tds[-5]
max_temp = list(tds[-5].stripped_strings)[0]
min_temp_td = tds[-2]
min_temp = list(tds[-2].stripped_strings)[0]
info['province'] = province
info['kity'] = kity
info['max_temp'] = max_temp
info['min_temp'] = min_temp
list_1.append(info)
# print("province:",province,"kity:", kity, "max_temp:", max_temp, "min_temp:", min_temp)
return list_1
def writeData(list):
headers = ('province', 'kity', 'max_temp', 'min_temp')
with open('weather1.csv', 'w', encoding='utf-8', newline='') as file_obj:
writer = csv.DictWriter(file_obj, headers)
writer.writeheader()
writer.writerows(list)
def main():
list = [] # 先建立一个空列表接收数据
url_1 = 'http://www.weather.com.cn/textFC/hb.shtml'
url_2 = 'http://www.weather.com.cn/textFC/db.shtml'
url_3 = 'http://www.weather.com.cn/textFC/hd.shtml'
url_4 = 'http://www.weather.com.cn/textFC/hz.shtml'
url_5 = 'http://www.weather.com.cn/textFC/hn.shtml'
url_6 = 'http://www.weather.com.cn/textFC/xb.shtml'
url_7 = 'http://www.weather.com.cn/textFC/xn.shtml'
url_8 = 'http://www.weather.com.cn/textFC/gat.shtml'
url_list = (url_1, url_2, url_3, url_4, url_5, url_6, url_7, url_8)
for url in url_list:
# print(url)
text = web_resquest(url)
# print(text)
list += web_parse(text)
print("完成一页:", url)
writeData(list)
print("爬取完毕!")
if __name__ == '__main__':
main()
第8期最后整理的代码:
import requests
from bs4 import BeautifulSoup
import csv
def web_resquest(url):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36'
}
response = requests.get(url, headers=headers)
text = response.content.decode('utf-8')
return text
def web_parse(text):
list_1 = []
# soup = BeautifulSoup(text, 'lxml') #最后一页标签不全就出现错误了
# 'html5lib'可以解决标签不全的问题,注意先安装才能使用 pip install html5lib
soup = BeautifulSoup(text, 'html5lib') # 将网页请求得到的结果,返回一个soup对象
# 先找到所有表的信息 div class_='conMidtab' 注间有个下划线
conMidtab = soup.find('div', class_='conMidtab') # 获取表间部分,简单理解就是只留下需要部分用来解析
# 接下来找每一个 直辖市或者省会的 table标签
tables = conMidtab.find_all('table')
for table in tables:
# 找table标签里面的tr标签 (来个切片把前2个过滤掉)
trs = table.find_all("tr")[2:]
# enumerate()这个方法 返回2个值 一个是值另一个是这个值所对应的索引
for index, tr in enumerate(trs):
info = {} # 建个空字典
tds = tr.find_all("td")
kity = list(tds[0].stripped_strings)[0] # 换成列表取数据,便可获取城市名称
# 进入下一个省份时,第一个是省份(也就是index为0时),第二个才是城市,有时省份和城市同名
# 所以这时要来个判断
if index == 0:
province = list(tds[0].stripped_strings)[0] # 获取省份名称
kity = list(tds[1].stripped_strings)[0] # 获取第二个才是正确的城市名称
# 获取最高气温和最低气温,利用倒数方法就不用判断顺序
max_temp = list(tds[-5].stripped_strings)[0] #倒数第5个td标签
min_temp = list(tds[-2].stripped_strings)[0] #倒数第5个td标签
# 将数据写入键值对
info['province'] = province
info['kity'] = kity
info['max_temp'] = max_temp
info['min_temp'] = min_temp
list_1.append(info)
# print("province:",province,"kity:", kity, "max_temp:", max_temp, "min_temp:", min_temp)
return list_1
def writeData(list):
headers = ('province', 'kity', 'max_temp', 'min_temp')
with open('weather1.csv', 'w', encoding='utf-8', newline='') as file_obj:
writer = csv.DictWriter(file_obj, headers)
writer.writeheader()
writer.writerows(list)
def main():
list = [] # 先建立一个空列表接收数据
url_1 = 'http://www.weather.com.cn/textFC/hb.shtml'
url_2 = 'http://www.weather.com.cn/textFC/db.shtml'
url_3 = 'http://www.weather.com.cn/textFC/hd.shtml'
url_4 = 'http://www.weather.com.cn/textFC/hz.shtml'
url_5 = 'http://www.weather.com.cn/textFC/hn.shtml'
url_6 = 'http://www.weather.com.cn/textFC/xb.shtml'
url_7 = 'http://www.weather.com.cn/textFC/xn.shtml'
url_8 = 'http://www.weather.com.cn/textFC/gat.shtml'
url_list = (url_1, url_2, url_3, url_4, url_5, url_6, url_7, url_8)
for url in url_list:
# print(url)
text = web_resquest(url)
# print(text)
list += web_parse(text)
print("完成一页:", url)
writeData(list)
print("爬取完毕!")
if __name__ == '__main__':
main()