用BeautifulSoup+requests+pyecharts爬取中国天气网,找到气温最高的前十城市,并进行数据的可视化。

目标网站:http://www.weather.com.cn/textFC/hb.shtml
我重点分析解析网页这个部分,请求网页这个模块就跳过吧。
打开浏览器的检查,找到我们想要的数据所存放的节点。
用BeautifulSoup+requests+pyecharts爬取中国天气网,找到气温最高的前十城市,并进行数据的可视化。_第1张图片

可以发现,这张网页的所有省份里面的城市信息是存放在(div class =‘conMidtab’)这个节点里面
可以用BeautiSoup来定位到这个节点假设我们已经获取了网页的文本信息并存放在html这个变量里面。

#解析网页我之所以用html5lib主要是因为在港澳台的天气网页中,网页代码不规范没有table的闭合标签
#html5lib的容错能力是最强的
soup = BeautifulSoup(html,'html5lib')
#直接定位到所有省份天气的节点。
conMidtab = soup.find('div',class='conMidtab')

继续检查找到一个省份的数据信息存放的节点,发现信息的存放在table这个标签里面
用BeautifulSoup+requests+pyecharts爬取中国天气网,找到气温最高的前十城市,并进行数据的可视化。_第2张图片
因为div class=conMidtab这个节点里面存放了所有省份的天气信息,现在我们要定位在一个省份的信息

tables = conMidtab.find_all('table')

继续检查,找到一个city的信息。
用BeautifulSoup+requests+pyecharts爬取中国天气网,找到气温最高的前十城市,并进行数据的可视化。_第3张图片
city信息是放在table下面的tr标签中,但是前面两个tr标签并没有存放信息,所以在进行遍历的时候我们要把前面两个tr用切片去掉。
用BeautifulSoup+requests+pyecharts爬取中国天气网,找到气温最高的前十城市,并进行数据的可视化。_第4张图片

for table in tables:
  trs = table.find_all('tr')[2:]  

然后我们来分析table下面的第三个tr,城市天气信息是放在每一个td中的。但是tr下面的第一个td存放的是一个省份名称。我们用河北省来分析,因为北京市和北京城市是同名的
用BeautifulSoup+requests+pyecharts爬取中国天气网,找到气温最高的前十城市,并进行数据的可视化。_第5张图片
用BeautifulSoup+requests+pyecharts爬取中国天气网,找到气温最高的前十城市,并进行数据的可视化。_第6张图片
总之就是第三个tr下面的第一个td里面存放的是省份不是city,而我们在遍历到第四个tr的时候,第一个td存放的就是city。所以我在处理这个部分的时候使用的是倒序取。代码如下,同理在找最高温度的时候,我也是采用倒序这个笨方法。

for tr in trs:
    #找到所有的td标签
    tds = tr.find_all('td')
    #[-8]是td中存放城市名称的位置
    city_td  = tds[-8]
    #city_td是一个标签类型,我们把他变成一个列表类型,再取第一个城市名称变成一个字符串。
    city = list(city_td.stripprd_strings)[0]
    max_temp_td = tds[-5]
    max_temp = list(max_temp_td.stripprd_strings)[0]
    #如果想把爬取的城市信息存放在本地,可以用with open as 这个方法。
    with open('temp.text','a',encoding='utf-8') as f:              
	f.write('{:^10}\t{:^4}\n'.format(city,max_temp,chr(12288)))
	f.flush()

下面就是解析一张网页的全部过程。用定义函数把这个过程封装起来。

def parserHTML(url):
    headers = {
             "User-Agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36"
        }
    r =requests.get(url,headers=headers)
    r.encoding = r.apparent_encoding
    html = r.text
    soup=BeautifulSoup(html,'html5lib')
    #定位到所有存放天气和城市信息大标签
    conMidtab = soup.find('div',class_='conMidtab')
    #定位到存放一个省份的天气信息的标签,还需要在每一个省份中找到每一个城市的信息。
    tables = conMidtab.find_all('table')
    for table in tables:
        trs = table.find_all('tr')[2:]
        for tr in trs:
            tds = tr.find_all('td')
            city_td = tds[-8]
            city = list(city_td.stripped_strings)[0]
            temp_td = tds[-5]
            max_temp = list(temp_td.stripped_strings)[0]
            with open('temp.text','a',encoding='utf-8') as f:
            	f.write('{:^10}\t{:^4}\n'.format(city,min_temp,chr(12288)))
            	f.flush()

如果我们想爬取中国所有city’的最高温度,还要然程序自动翻页。首先找到网页翻页的规律,或者用笨办法把所有的网页列下来,然后一个一个的遍历。我采用的是笨办法。
华北:http://www.weather.com.cn/textFC/hb.shtml
东北:http://www.weather.com.cn/textFC/db.shtml
华东:http://www.weather.com.cn/textFC/hd.shtml

def main():
    urls=[
            
            'http://www.weather.com.cn/textFC/hb.shtml',
            'http://www.weather.com.cn/textFC/db.shtml',
            'http://www.weather.com.cn/textFC/hd.shtml',
            'http://www.weather.com.cn/textFC/hz.shtml',
            'http://www.weather.com.cn/textFC/hn.shtml',
            'http://www.weather.com.cn/textFC/xb.shtml',
            'http://www.weather.com.cn/textFC/xn.shtml',
            'http://www.weather.com.cn/textFC/gat.shtml'
            ]
    for url in urls:
        parserHTML(url)
  
if __name__=='__main__':
    main()

如何进行找到气温最高的前十城市呢。我的思路是:
1.是要把我们爬取的下来的信息,放在一个空列表 Temp=[] 里面。可以在解析函数之前定义一个空列表。

#把max_temp变成一个整型,方便后面的排序,这是放在parserHTML(url)中,来存放信息的。
Temp.append ({'city':city,'max_temp':int(max_temp)})

2.把爬取到的city和max_temp存放在里面,并对max_temp进行排序。

#按照从大到小的顺序对max_temp进行排序
Temp.sort(key=lambda x:x['max_temp'],reverse=True)

3.然后导入pyecharts库,以city为横轴,以温度为纵轴,建立一个直方图。这里我使用了map函数,对city和max_temp进行映射

#取出温度最高的前十城市
List = Temp[0:10]
#把城市名称取出来,以列表的形式返回。map函数会返回一个map对象。
cities = list(map(lambda x:x['city'] ,List))
#把温度信息取出来,以列表的形式返回。
temps = list(map(lambda x:x['min_temp'],List))
bar=Bar("中国最低气温排行榜")
bar.add('',cities,temps)
bar.render('temp.html')

这样就画出了一个简单的直方图,进行了一个简单的数据可视化。
在命令行中安装pyecharts:pip install pyecharts
pyecharts这个库很强大,我也只是做了一个简单的模仿。
这篇文章里面详细的介绍了pyecharts的用法:https://github.com/pyecharts/pyecharts

好了全部代码如下

import requests
from bs4 import BeautifulSoup
from pyecharts import Bar

Temp = []
def parserHTML(url):
    headers = {
             "User-Agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36"
        }
    r =requests.get(url,headers=headers)
    r.encoding = r.apparent_encoding
    html = r.text
    soup=BeautifulSoup(html,'html5lib')
    #定位到所有存放天气和城市信息大标签
    conMidtab = soup.find('div',class_='conMidtab')
    #定位到存放一个省份的天气信息的标签,还需要在每一个省份中找到每一个城市的信息。
    tables = conMidtab.find_all('table')
    for table in tables:
        trs = table.find_all('tr')[2:]
        for tr in trs:
            tds = tr.find_all('td')
            city_td = tds[-8]
            city = list(city_td.stripped_strings)[0]
            temp_td = tds[-5]
            max_temp = list(temp_td.stripped_strings)[0]
            Temp.append ({'city':city,'max_temp':int(max_temp)})
            with open('temp.text','a',encoding='utf-8') as f:
            	f.write('{:^10}\t{:^4}\n'.format(city,max_temp,chr(12288)))
            	f.flush()
            #print(city,min_temp)
            
def main():
    print('{:^10}\t{:^4}'.format('城市','最高气温',chr(12288)))
    urls=[
            
            'http://www.weather.com.cn/textFC/hb.shtml',
            'http://www.weather.com.cn/textFC/db.shtml',
            'http://www.weather.com.cn/textFC/hd.shtml',
            'http://www.weather.com.cn/textFC/hz.shtml',
            'http://www.weather.com.cn/textFC/hn.shtml',
            'http://www.weather.com.cn/textFC/xb.shtml',
            'http://www.weather.com.cn/textFC/xn.shtml',
            'http://www.weather.com.cn/textFC/gat.shtml'
            ]
    for url in urls:
        parserHTML(url)
    Temp.sort(key=lambda x:x['max_temp'],reverse=True)
    List = Temp[0:9]
    #cities = []
    #for city_temp in List:
        #city = city_temp['city']
        #cities.append(city)
    cities= list(map(lambda x:x['city'],List))
    temps = list(map(lambda x:x['max_temp'],List))

    
    bar=Bar("中国最高气温排行榜")
    bar.add('',cities,temps)
    bar.render('temp.html')
    
    
if __name__=='__main__':
    main()

你可能感兴趣的:(python)