目标
# !/usr/bin/python
# Filename: 用bs4实现抓取全国天气预报.py
# Data : 2020/07/29
# Author : --king--
# ctrl+alt+L自动加空格格式化
from bs4 import BeautifulSoup
import requests
import csv
# 获取网页源代码
def page_html(url):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36'}
re = requests.get(url, headers=headers)
page_html = re.content.decode('utf-8')
# print(page_html)
return page_html
def urls(url):
page_content = page_html(url)
soup = BeautifulSoup(page_content, 'html5lib')
lq_contentboxTab2 = soup.find('ul', 'lq_contentboxTab2')
a_tags = lq_contentboxTab2.find_all('a')
urls = []
for a_tag in a_tags:
a = a_tag.get('href')
area_url = 'http://www.weather.com.cn/' + a
urls.append(area_url)
return urls
# 用bs4抓取想要的信息
def weather_dict(page_html):
# 如果用lxml解析没法补全部分标签,可以采用html5lib
# soup = BeautifulSoup(page_html,'lxml')
soup = BeautifulSoup(page_html, 'html5lib')
# 先获取华北/东北/华东/华中/华南/西北/西南/港澳台的li标签
# 对其中一个li标签进行抓取
conMidtab = soup.find('div',class_ = 'conMidtab')
tables = conMidtab.find_all('table')
for table in tables:
# 找所有的tr
trs = table.find_all('tr')[2:]
# 由于温度要与城市对应,为了避免省会的干扰,需要引入索引值
# enumerate会返回两个值
for index,tr in enumerate(trs):
# 找到所有td
tds = tr.find_all('td')
# 获取城市名
# 由于取[0]会取到省名
city_td = tds[0]
# 解决直辖市和省份问题,通过判断下表索引,来取第一个值
if index == 0:
city_td = tds[1]
# 返回的是一个生成器,可以以列表的形式切片取出
# 用去除空格的字符串输出
city = list(city_td.stripped_strings)[0]
# 获取最低温度
temp_low_td = tds[-2]
temp_low = list(temp_low_td.stripped_strings)[0]
print('城市:',city,'温度:',temp_low)
# def write_Data(weather_dict):
#
# pass
# # with open('/result/weather.csv','w',encoding='utf-8-sig',newline='') as f:
# # writer = csv.DictWriter(f,fieldnames=[city,temp])
# # writer.writeheader()
# # for weather in weather_dict:
# # writer.writerow(weather)
def main():
# 用湖北省的url进行测试
url = 'http://www.weather.com.cn/textFC/hb.shtml'
# 从页面的li标签获取每个区域的url
url_list = urls(url)
for area_url in url_list:
page_content = page_html(area_url)
weather_dict(page_content)
# write_Data(weather_Data)
if __name__ == '__main__':
main()
需要注意的地方
- 抓取逻辑,以河北省的天气页面为入口,确定每个区域的urls
- append()没有返回值,要注意,如果强行赋值会报错
- 用bs4抓取urls中某个url的城市名和最低气温
- bs4的解释器用xlml时对标签补全不完整,需要改为html5lib解释器,否则抓港澳台区域会出错。
- 省会城市的抓取会出错,需要调用enumerate()函数,利用其index索引返回值,对tds列表里的第一个城市进行判断,第一个城市取[1] ,其他城市取[0]
- 由于数据只有两条,所以没有进行csv写入,而是打印,代码中保留了部分写入格式,稍作修改即可写入
- 本次案例考验了对html代码的分析能力,逻辑处理能力和排错能力。