python3爬取当天最高气温

概述

学习了网易云课堂上,知了的一个爬取全国最热城市的视频,花了一天时间自己整理和手动实现了一下,现总结于此,方便后续翻阅或给其他朋友有所帮助。

分析与实现

中国天气网页面分析

分析的网页地址:http://www.weather.com.cn/textFC/hb.shtml
用chorme打开如上地址

获取天气数据的url

可发现全国主要城市按照大区分类(华北、东北、华东、华中、华南、西北、西南、港澳台),位于如下标签内,可以通过解析获得所有天气的链接地址

<ul class="lq_contentboxTab2">
            <li style="background:transparent url(/m2/i/forecast/textFC/c_tabm_bar.png);"><span><a href="/textFC/hb.shtml">华北</a></span></li>
            <li><span><a href="/textFC/db.shtml">东北</a></span></li>
            <li><span><a href="/textFC/hd.shtml">华东</a></span></li>
            <li><span><a href="/textFC/hz.shtml">华中</a></span></li>
            <li><span><a href="/textFC/hn.shtml">华南</a></span></li>
            <li><span><a href="/textFC/xb.shtml">西北</a></span></li>
            <li><span><a href="/textFC/xn.shtml">西南</a></span></li>
            <li><span><a href="/textFC/gat.shtml">港澳台</a></span></li>
        </ul>

由于是相对路径,所有要对路径进行拼接

def get_host(url):
    """
    获取url中的主机地址,用于构建http请求全路径
    :param url:
    :return:
    """
    parse = urlparse(url)
    return url.split(parse.path)[0]


def get_urls(html, url):
    """
    提取按区域抓取天气的url集合
    :param soup:
    :return:
    """
    host = get_host(url)

    soup = BeautifulSoup(html, 'lxml')
    ul = soup.find(name="ul", attrs={"class": "lq_contentboxTab2"})
    a_list = ul.find_all("a")
    url_list = []
    for a in a_list:
        new_url = host + a.attrs["href"]
        if new_url != url:
            url_list.append(new_url)

    return url_list

除了港澳台,其他天气页面规则大体如下

页面中包含的是最近7天(包括当天)的天气,只是通过style=”display:none;”进行了隐藏

<div class="hanml">
                <div class="conMidtab">...</div>
                <div class="conMidtab" style="display:none;">...</div>
                ...
            </div>

只需要抓取第一个div,对应的class=”conMidtab”便包含当天的天气,然后是每个省/直辖市归类城市天气在一个table中,
由于table的第1.2个tr为表头,所以需要过滤
省:
位于第3个tr的第1个td内

<td width="74" rowspan="17" class="rowsPan">
                            <a href="/textFC/beijing.shtml" target="_blank">北京</a>
                        </td>

城市
如果是第3个tr,则位于第2个td内,其他tr则位于第1个td内

<td width="83" height="23">
                            <a href="http://www.weather.com.cn/weather/101010100.shtml" target="_blank">北京</a>
                        </td>

气温
白天最高气温
如果是第3行,位于第5个td中。否则,位于第4个td中
夜间最低气温
如果是第3行,位于第8个td中。否则,位于第7个td中

def get_temperatures(html):
    if html is None:
        print("网页内容为空!!!")
        return
    """
    获取温度信息
    :return:
    """
    soup = BeautifulSoup(html, 'lxml')
    province = None  # 省
    # 找到当天的
    conMidtab = soup.find("div", attrs={"class": "conMidtab"})
    # 找到所有省的
    conMidtab2_list = conMidtab.find_all("div")
    for conMidtab2 in conMidtab2_list:
        # 对应所有市的
        tr_list = conMidtab2.find_all("tr")[2:]
        for index, tr in enumerate(tr_list):
            td_list = tr.find_all("td")
            if index == 0:  # 包含省信息
                province = td_list[0].text.replace("\n", "")
                city = province + td_list[1].text.replace("\n", "")
                min_temp = td_list[7].text.replace("\n", "")
            else:
                city = province + td_list[0].text.replace("\n", "")
                min_temp = td_list[6].text.replace("\n", "")

                TEMPTATURE_LIST.append({"city": city, "min": min_temp})

    print("一次分析结束")

港澳台特殊对待(:0 好像也符合国情)

实际编码过程中发现,该页面的内容需要js渲染才能看到真正完整的页面内容,所以无法通过bs4按照上面的那种情况去处理。这里我采用的是最笨的方法,查询出所有的tr然后进行判断处理。

def get_gat_temperatures(url):
    """
    港澳台的页面需要页面js调用才能得到完整的html内容,所以不能正常分析得到
    :param url:
    :return:
    """
    html = get_html(url)
    # with open("te.html", "wb") as fp:
    #     fp.write(html)
    # html = ""
    # with open("te.html", "r", encoding="utf-8") as fp:
    #     html = fp.read()

    soup = BeautifulSoup(html, 'html.parser')

    tr_list = soup.find_all('tr')

    gat_list = ['香港', '澳门', '台北', '高雄', '台中']

    index = 0
    for tr in tr_list:
        if (index < 2 and tr.text.find(gat_list[index]) > -1) or (index == 2 and tr.text.find(gat_list[index]) > -1):
            # 如果是香港或澳门,或者台北
            td_list = tr.find_all("td")
            province = td_list[0].text.replace("\n", "")
            city = province + td_list[1].text.replace("\n", "")
            min_temp = td_list[7].text.replace("\n", "")
            index += 1
            TEMPTATURE_LIST.append({"city": city, "min": min_temp})

        elif 2 < index < len(gat_list) and tr.text.find(gat_list[index]) > -1:
            # 台湾其他
            td_list = tr.find_all("td")
            city = province + td_list[0].text.replace("\n", "")
            min_temp = td_list[6].text.replace("\n", "")
            index += 1
            TEMPTATURE_LIST.append({"city": city, "min": min_temp})

    print("港澳台分析结束")

由于最高气温在7:30以后就变成“-”了,所以获取最低气温,展示时为随机取20个城市温度
源码地址:https://gitee.com/fan1989800/spider_weather

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值