2021-04-01

爬取全国各城市当天天气信息

准备工作

  • 网页地址:http://www.weather.com.cn/textFC/hb.shtml
  • 打开页面后发现要爬取的内容是在表格内,如下图所示,我们需要省份、城市名称,最高气温和最低气温。


    image.png

    *在“北京”上右键--检查(不要在空白处)


    image.png
image.png

准备工作小结

  • 要爬取的内容全部是在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()
image.png

你可能感兴趣的:(2021-04-01)