python3 爬虫—爬取天气预报多个城市七天信息(三)

本文介绍了一种使用Python的requests库和BeautifulSoup库从中国天气网抓取指定城市七天天气预报的方法,并将获取的数据保存到CSV文件中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、内容:

       利用BeautifulSoup抓取中国天气网各个城市7天的 时间 天气状态 最高温 最低温 的相关信息,并记录保存在本地csv表格文件中。

以杭州为例:http://www.weather.com.cn/weather/101210101.shtml


爬取的页面截图:


html获取信息截图:


二、原理:

     1.利用requests获取请求 、BeautifulSoup抓取数据。

     2.通过readlines()读取city.txt文件的天气接口来生成各城市的url

     3.通过第三方库csv将抓取的到的数据写入weather.csv表格

 获取URL: 

#  获取每个城市对应天气的url
def get_url(city_name):
    url = 'http://www.weather.com.cn/weather/'
    with open('D:\py_project\weather\city.txt', 'r', encoding='UTF-8') as fs:
        lines = fs.readlines()
        for line in lines:
            if(city_name in line):
                code = line.split('=')[0].strip()
                return url + code + '.shtml'
    raise ValueError('invalid city name')

发送URL GET请求,获取response:

#  对网页获取get请求,得到的是response对象
def get_content(url, data=None):
    #  模拟浏览器访问
    header = {
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
        'Accept-Encoding': 'gzip, deflate, sdch',
        'Accept-Language': 'zh-CN,zh;q=0.8',
        'Connection': 'keep-alive',
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.235'
    }
    #  超时,取随机数是因为防止被网站认定为网络爬虫
    timeout = random.choice(range(80, 180))
    while True:
        try:
            #  获取请求数据
            rep = requests.get(url, headers=header, timeout=timeout)
            rep.encoding = 'utf-8'
            break
        except socket.timeout as e:
            print('3:', e)
            time.sleep(random.choice(range(8, 15)))
        except socket.error as e:
            print('4:', e)
            time.sleep(random.choice(range(20, 60)))
        except http.client.BadStatusLine as e:
            print('5:', e)
            time.sleep(random.choice(range(30, 80)))
        except http.client.BadStatusLine as e:
            print('6:', e)
            time.sleep(random.choice(range(5, 15)))

    return rep.text

抓取天气信息:

# 获取html中我们所需要的字段:
def get_data(html_text, city_name):
    #  final元组存放七天的数据
    final = []
    t = []
    t.append(city_name)
    final.append(t)
    bs = BeautifulSoup(html_text, "html.parser")  # 创建BeautifulSoup对象,解析器为:html.parser
    body1 = bs.body  # 获取body部分

    #  print(body1)
    data = body1.find('div', {'id': '7d'})  # 找到id为7d的div
    ul = data.find('ul')  # 获取ul部分
    li = ul.find_all('li')  # 获取所有的li

    for day in li:   # 对每个li标签中的内容进行遍历
        # temp代存每日的数据
        temp = []
        #  添加日期
        data = day.find('h1').string   # 找到日期
        temp.append(data)  # 添加到temp中

        inf = day.find_all('p')  # 找到li中的所有p标签
        #  添加天气状况
        temp.append(inf[0].string)  # 第一个p标签中的内容(天气状况)加到temp中
        #  添加最高气温
        if inf[1].find('span') is None:
            temperature_highest = None  # 天气当中可能没有最高气温(傍晚)
        else:
            temperature_highest = inf[1].find('span').string  # 找到最高气温
            temperature_highest = temperature_highest.replace('℃', '')
        temp.append(temperature_highest)  # 将最高温添加进去
        # 添加最低气温
        temperature_lowest = inf[1].find('i').string  # 找到最低温
        temperature_lowest = temperature_lowest.replace('℃', '')  # 最低温度后面有个℃,去掉这个符号
        temp.append(temperature_lowest)  # 将最低温添加上去

        final.append(temp)  # 将temp 加到final中

    return final


保存信息到CSV中:

# 将抓取出来的数据写入文件
def write_data(city_name, data, file_name):
    with open(file_name, 'a', errors='ignore', newline='') as f:
        f_csv = csv.writer(f)
        f_csv.writerows(data)
        print('%s 天气已添加成功' % city_name)

三、完整代码:

import requests
import csv
import random
import time
import socket
import http.client
from bs4 import BeautifulSoup


#  获取每个城市对应天气的url
def get_url(city_name):
    url = 'http://www.weather.com.cn/weather/'
    with open('D:\py_project\weather\city.txt', 'r', encoding='UTF-8') as fs:
        lines = fs.readlines()
        for line in lines:
            if(city_name in line):
                code = line.split('=')[0].strip()
                return url + code + '.shtml'
    raise ValueError('invalid city name')


#  对网页获取get请求,得到的是response对象
def get_content(url, data=None):
    #  模拟浏览器访问
    header = {
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
        'Accept-Encoding': 'gzip, deflate, sdch',
        'Accept-Language': 'zh-CN,zh;q=0.8',
        'Connection': 'keep-alive',
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.235'
    }
    #  超时,取随机数是因为防止被网站认定为网络爬虫
    timeout = random.choice(range(80, 180))
    while True:
        try:
            #  获取请求数据
            rep = requests.get(url, headers=header, timeout=timeout)
            rep.encoding = 'utf-8'
            break
        except socket.timeout as e:
            print('3:', e)
            time.sleep(random.choice(range(8, 15)))
        except socket.error as e:
            print('4:', e)
            time.sleep(random.choice(range(20, 60)))
        except http.client.BadStatusLine as e:
            print('5:', e)
            time.sleep(random.choice(range(30, 80)))
        except http.client.BadStatusLine as e:
            print('6:', e)
            time.sleep(random.choice(range(5, 15)))

    return rep.text


# 获取html中我们所需要的字段:
def get_data(html_text, city_name):
    #  final元组存放七天的数据
    final = []
    t = []
    t.append(city_name)
    final.append(t)
    bs = BeautifulSoup(html_text, "html.parser")  # 创建BeautifulSoup对象,解析器为:html.parser
    body1 = bs.body  # 获取body部分

    #  print(body1)
    data = body1.find('div', {'id': '7d'})  # 找到id为7d的div
    ul = data.find('ul')  # 获取ul部分
    li = ul.find_all('li')  # 获取所有的li

    for day in li:   # 对每个li标签中的内容进行遍历
        # temp代存每日的数据
        temp = []
        #  添加日期
        data = day.find('h1').string   # 找到日期
        temp.append(data)  # 添加到temp中

        inf = day.find_all('p')  # 找到li中的所有p标签
        #  添加天气状况
        temp.append(inf[0].string)  # 第一个p标签中的内容(天气状况)加到temp中
        #  添加最高气温
        if inf[1].find('span') is None:
            temperature_highest = None  # 天气当中可能没有最高气温(傍晚)
        else:
            temperature_highest = inf[1].find('span').string  # 找到最高气温
            temperature_highest = temperature_highest.replace('℃', '')
        temp.append(temperature_highest)  # 将最高温添加进去
        # 添加最低气温
        temperature_lowest = inf[1].find('i').string  # 找到最低温
        temperature_lowest = temperature_lowest.replace('℃', '')  # 最低温度后面有个℃,去掉这个符号
        temp.append(temperature_lowest)  # 将最低温添加上去

        final.append(temp)  # 将temp 加到final中

    return final


# 将抓取出来的数据写入文件
def write_data(city_name, data, file_name):
    with open(file_name, 'a', errors='ignore', newline='') as f:
        f_csv = csv.writer(f)
        f_csv.writerows(data)
        print('%s 天气已添加成功' % city_name)


if __name__ == '__main__':

    cities = input('请输入城市名称(一个或多个,以空格隔开): ').split(' ')
    for city in cities:
        url = get_url(city)  # 获取城市天气的url
        html = get_content(url)  # 获取网页html
        result = get_data(html, city)  # 爬去城市的信息
        write_data(city, result, 'D:\py_project\weather\weather.csv')  # 将爬取得信息填入表格文件


四、运行结果:


以下是爬取天气数据并可视化的方法: 1. 爬取天气数据 ```python import requests from bs4 import BeautifulSoup import csv # 获取网页内容 url = 'http://www.weather.com.cn/weather/101010100.shtml' res = requests.get(url) res.encoding = 'utf-8' soup = BeautifulSoup(res.text, 'html.parser') # 获取城市名称 city = soup.select('.crumbs a')[2].text # 获取每天的天气信息 days = soup.select('.t .clearfix') data = [] for day in days: date = day.select('.day')[0].text high_temp = day.select('.tem span')[0].text low_temp = day.select('.tem i')[0].text weather = day.select('.wea')[0].text wind = day.select('.win')[0].text.strip() data.append([date, high_temp, low_temp, weather, wind]) # 将数据存储到csv文件中 with open(f'{city}.csv', 'w', newline='', encoding='utf-8') as f: writer = csv.writer(f) writer.writerow(['日期', '最高温', '最低温', '天气', '风向']) for row in data: writer.writerow(row) ``` 2. 可视化平均气温走势折线图 ```python import pandas as pd import matplotlib.pyplot as plt # 读取csv文件 df = pd.read_csv(f'{city}.csv', encoding='utf-8') # 计算平均温度 df['平均温度'] = (df['最高温'] + df['最低温']) / 2 # 绘制折线图 plt.plot(df['日期'], df['平均温度'], label=city) plt.legend() plt.xlabel('日期') plt.ylabel('平均气温') plt.title(f'{city}一年平均气温走势') plt.show() ``` 3. 统计各类天气的天数并绘制条形图 ```python # 统计各类天气的天数 weather_count = df['天气'].value_counts() # 计算适合旅游的城市指数 weather_index = weather_count['多云'] * 0.3 + weather_count['晴'] * 0.4 + weather_count['阴'] * 0.3 # 绘制条形图 weather_count.plot(kind='bar') plt.xlabel('天气') plt.ylabel('天数') plt.title(f'{city}各类天气的天数') plt.show() print(f'{city}的适合旅游的城市指数为:{weather_index}') ``` 4. 统计每个月的平均气温并绘制折线图 ```python # 将日期转换为月份 df['月份'] = pd.to_datetime(df['日期']).dt.month # 按月份分组计算平均气温 month_avg_temp = df.groupby('月份')['平均温度'].mean() # 绘制折线图 plt.plot(month_avg_temp.index, month_avg_temp.values, label=city) plt.legend() plt.xlabel('月份') plt.ylabel('平均气温') plt.title(f'{city}每个月的平均气温') plt.show() # 计算最适合旅游的月份 best_month = month_avg_temp.idxmax() print(f'{city}最适合旅游的月份是{best_month}月') ``` 5. 统计平均气温在18~25度,风力小于5级的天数并判断哪个城市更适合居住 ```python # 计算符合条件的天数 temp_count = ((df['最高温'] + df['最低温']) / 2).between(18, 25).sum() wind_count = (df['风向'].str.contains('微风')).sum() # 判断哪个城市更适合居住 if temp_count > wind_count: print(f'{city}更适合居住') else: print(f'{city2}更适合居住') ```
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值