zoukankan      html  css  js  c++  java
  • 【Python爬虫学习实践】基于BeautifulSoup的网站解析及数据可视化

    在上一次的学习实践中,我们以Tencent职位信息网站为例,介绍了在爬虫中如何分析待解析的网站结构,同时也说明了利用Xpath和lxml解析网站的一般化流程。在本节的实践中,我们将以中国天气网为例,并基于Beautiful Soup库对其进行数据解析,最后再简单说明pyecharts数据可视化。

    中国天气网网址:http://www.weather.com.cn/textFC/hb.shtml

    image

    和之前的Tencent职位信息实践一样,我们先来分析一下我们所爬取的网站的结构。在中国天气网中,我们可以看到其是按照地区进行了分类,如华北、东北、华东、华中等等,并且每一个地区都对应着一个不同的页面。

    接下来我们再来看看我们需要获取的数据信息。如下图所示,每一个页面的数据结构都是以省市为块的城市数据列表,而这些列表中的数据就是我们需要提取的信息。由于现在当地时间为夜晚,白天的信息也就没有显示了,因此在此以爬取夜间的天气现象和最低气温为例,来说明实践中的Beautiful Soup数据提取的一般化流程。(Ps.注意这里显示了一周的天气情况,而后面的天气信息都是完整的,后续会介绍如何爬取这些不同天的数据)

    image

    通过上述简单分析,我们不难知道其实本次的数据获取只需要得到相应的URL地址,通过请求获取其HTML源代码,再利用解析库解析出相应的数据即可。下面我们就对此分过程介绍。

    Step1——分析天气URL

    从之前的介绍我们知道中国天气网划分了几个不同的地区,每一个地区都对应着一个URL,现在我们就先来看看这些URL的构成法。

    华北: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

    经过观察分析,发现这几个URL的域名都是一样的,只是后面的path的文件名不同,因此我们可以大胆地推测其URL构成法为:’http://www.weather.com.cn/textFC/+{}.shtml’,其中{}为地区名拼音缩写

    接下来,我们再通过其他地区地URL来验证我们地推测。(十多秒过后…)嗯,结果发现和我们的推测是一样的,如港澳台就是引用’gat.shtml’。如此一来,URL的获取工作就好了。(其实,天气地区个数较少,网页URL也比较少,我们也可以手动获取,不过这样代码就会显得有些冗长)

    ## 遍历获取各地区天气URL并传入解析函数
    
    url = 'http://www.weather.com.cn/textFC/{}.shtml'
    for flag in ('hb', 'db', 'hd', 'hz', 'hn', 'xb', 'xn', 'gat'):
        parse_page_soup(url.format(flag))

    Step2——分析数据信息结构

    在获取了天气URL后,接下来就要分析我们所需提取的数据结构是怎样的。下面以华北地区为例,可以看到其省市天气数据结构如下。发现其数据都放在了一个class为conMidtab的div标签中,而这样的标签共有7个,那么又分别代表什么呢?细心观察后发现只有1个的display 样式为block,而其他的都是none。其实当我们点击其他日期的时候,我们会发现其他一个变成了block,而之前的那个变成了none,所以这些其实就是代表不同时间的天气数据,进入节点查看具体信息后我们也发现这些节点的结构都一样,也再次说明这就是用来控制显示不同日期数据的。

    image

    每一个日期信息的获取的原理都是一样的,那么接下来我们就以北京(今天)为例,进一步分析其数据组织结构。浏览源码我们可以发现在comMidtab的div标签下有5个comMidtab2的子div标签,这些其实就是代表华北地区的5个省市,每一个div为一个省市天气的列表。

    image

    接下来,在每一个子div中,我们可以找到一个table标签,而里面的tbody标签下又有若干个tr标签,扫描后可得知这些tr就是每一个省市数据列表中的行。

    image

    我们进一步观察每个tr标签的内容,可以知道前两个tr标签是列表的数据信息头,而我们真正要获取的数据为之后的tr标签。

    image

    这么一来,我们便可以结合解析库来获取相应的数据信息了。不过在解析的时候要注意一个问题,那就是并不是所有的tr标签的子结构都是一样的。如下面的北京和海淀,北京比海淀多了第一个td,从图中可以看出其实这是旁边的省市名,因此在解析时需要设定一个好的解析策略。

    image

    ##数据解析
    import requests
    from bs4 import BeautifulSoup
    
    HEADERS = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.92 Safari/537.36',
    }
    
    # 设置全局变量,用于保存提取的数据
    WEATHER_ALL = []
    
    # 解析数据
    def parse_page_soup(url):
        response = requests.get(url, headers=HEADERS)
        text = response.content.decode('utf-8')
        soup = BeautifulSoup(text, 'html5lib')    #采用html5lib的解析器
        conMidtab = soup.find('div', attrs={'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')
                data = {
                    'city': list(tds[-8].stripped_strings)[0],    #为统一结构,倒序取值
                    'weather': list(tds[-4].stripped_strings)[0],
                    'min_temp': int(list(tds[-2].stripped_strings)[0])
                }
                WEATHER_ALL.append(data)

    image

    这里需要说明的是,为什么我们在解析时采用的时html5lib的解析器呢?其实,采用lxml解析会快很多,但这不安全,因为在本次的天气网中,并不是所有的天气页面都是很规范的。我们可以先试一下用lxml来解析,看看会发生什么?如下图,我们发现在解析港澳台地区的时候发生了错误,那么是为什么呢?

    image

    在错误中提示列表越界,说明没有找到对应的标签,是我们提取出问题了?其实不然,之前在html5lib解析器下都是可以的,说明问题只出在了解析方式上,而这两种解析器的区别重在容错性。查看源码我们发现,港澳台地区的网页并不是那么规范的,在数据表table标签中,其有前标签而缺少了尾标签</table>,也因此容错性不及html5lib的lxml解析就会出错,所以我们在写爬虫时要先确定好解析器种类,也可使用动态解析器。

    image

    Step3——数据可视化

    在爬取获得数据后,接下来我们简单地按照最低气温排序并对前12个城市的数据进行可视化处理。

    对于排序,因为我们存储体的是列表对象,可以使用内置的sort()方法,而我们存储的元素类型为字典结构并对某一属性值(最低气温)排序,因此调用方法时我们需要传入一个排序关键字参数key,并通过lambda表达式使其与字典中的属性相关联(这里也恰好解释了之前获取最低气温时为什么要存储为int类型)。

    于可视化处理,我们可以借助一个名为pyecharts的工具库,使用它可以很方便地绘制各类地数据图。安装方法也很简单,使用pip安装即可(pip install pyecharts),具体的使用方法在此不在叙述,大家可以参看中文文档http://pyecharts.org/#/

    ## 对数据排序并按照最低气温取前12个城市制作可视化图表
    from pyecharts import Bar
    
    WEATHER_ALL.sort(key=lambda data: data['min_temp'])
    data = WEATHER_ALL[0:12]
    
    cities = list(map(lambda x: x['city'], data))        #横轴数据列表
    temps = list(map(lambda x: x['min_temp'], data))    #纵轴数据列表
    chart = Bar("中国天气最低气温排行榜")        #实例化图表并传入标题参数
    chart.add('',cities,temps)            #添加一个图表关系
    chart.render('temperature.html')        #绘制并存储为html文件

    image

    另外,在安装pyecharts时显示安装成功,然而实际上使用时可能会出现如下的错误,提示未找到pyecharts_snapshot模块,具体解决措施可参看中文文档(见下图)image

    image


    至此,上述便是基于Beautiful Soup库解析网站的一个实践,同时也简单地介绍了数据可视化的内容。其实无论Beautiful Soup还是之前的lxml,解析的一般流程都大致相同,只是适用的环境和解析速度有所区别,在实际的爬取工作中还需要认真分析网页结构,采取合适的爬取机制和手段。

  • 相关阅读:
    公用表表达式(CTE)的递归调用
    c# 如何让tooltip显示文字换行
    实战 SQL Server 2008 数据库误删除数据的恢复
    SQL SERVER数据库中 是否可以对视图进行修改删除
    asp.net中实现文件批量上传
    sql server 2008学习2 文件和文件组
    sql server 2008学习3 表组织和索引组织
    sql server 2008学习4 设计索引的建议
    sql server 2008学习10 存储过程
    .net 调用 sql server 自定义函数,并输出返回值
  • 原文地址:https://www.cnblogs.com/Unikfox/p/9688807.html
Copyright © 2011-2022 走看看