基于Python爬虫的按省份爬取中国天气网的天气信息
纤雨-初晴
2024年10月10日 21:30

1.首先是看了合肥的天气,链接如下:

https://www.weather.com.cn/weather/101220101.shtml。随后看了地区的天气,发现每个地方对应一个编号,这里合肥(101220101)。确定了url的格式。

2.最后在网站的源代码中找到了js,存放了这些数据。

注意到了这里可以截取等号后的部分。后面的是一个嵌套的字典。这样我就能通过访问这个js来获取一个省份对应的市的area_id数组,从而用for循环就能实现对各个市的天气网站进行遍历。

3.第三步是聚焦一个城市,这里用合肥的举例。看合肥的天气网页的源代码,找到需要爬取的目标。这一步是比较轻松的,很容易就找到了数据在类型为t clearfix的ul标签下。目标数据在li里。

4.针对第二步和第三步,编写两个函数:get_AnHui_areaid()、get_weather_data(url)。(本次实验中爬取的是安徽的天气,所以第一个函数命名获取安徽的市的代号数组)

为了增加代码的健壮性,这里使用了try/except结构。

这里是city_data的部分。

这个函数根据每个数据的标签,把数据清洗出来。

  1. 随后将数据写到本地文件中,实验就结束了。得到的数据集如下:

代码如下:

import json

import requests

from bs4 import BeautifulSoup

import re

# 定义全局常量

URL = "https://j.i8tq.com/weather2020/search/city.js"

FILENAME = 'AnHui_weather_data.txt'

# 获取安徽省所有城市的区域ID

def get_AnHui_areaid():

   try:

       # 使用requests库发送请求

       response = requests.get(URL)

       # 解析JSON数据

       city_data = json.loads(response.text.split('=')[1].strip())

   except Exception as e:

       print(f"Error occurred while fetching area ids: {e}")

       return []

   # 提取安徽省所有城市的区域ID

   AnHui_area_ids = [data.get('AREAID') for city, counties in city_data.get("安徽", {}).items() for county, data in counties.items() if data.get('AREAID')]

   return AnHui_area_ids

# 根据URL获取天气数据

def get_weather_data(url):

   try:

       # 使用requests库发送请求

       response = requests.get(url)

       # 使用BeautifulSoup解析HTML

       soup = BeautifulSoup(response.content, "html.parser")

   except Exception as e:

       print(f"Error occurred while fetching weather data: {e}")

       return []

   # 提取城市名称

   crumbs_div = soup.find('div', class_='crumbs fl')

   city_name = ', '.join(tag.text.strip() for tag in crumbs_div.find_all('a'))

   weather_data = []

   # 遍历每一天的天气数据

   for day in soup.find('ul', 't clearfix').find_all('li'):

       # 提取日期

       date = day.find('h1').get_text()

       # 提取天气情况

       weather_condition = day.find('p', 'wea').get_text()

       # 提取最高温度

       temperature_span = day.find('p', 'tem').find('span')

       hightem = temperature_span.get_text() if temperature_span is not None else 'N/A'

       # 提取最低温度

       lowtem = day.find('p', 'tem').find('i').get_text()

       # 提取风向

       wind = '-'.join(re.findall('(?<= title=").*?(?=")', str(day.find('p', 'win').find('em'))))

       # 提取风力等级

       level = day.find('p', 'win').find('i').get_text()

       # 将提取的数据添加到列表中

       weather_data.append({

           "城市": city_name,

           "日期": date,

           "天气情况": weather_condition,

           "最低温度": lowtem,

           "最高温度": hightem,

           "风向": wind,

           "等级": level

      })

   return weather_data

# 定义一个函数,将天气数据写入文件

def write_to_file(weather_data, filename=FILENAME):

   try:

       # 打开文件,准备写入

       with open(filename, 'w', encoding='utf-8') as file:

           current_city = ""

           # 遍历天气数据

           for data in weather_data:

               city = data['城市']

               # 如果当前城市与上一个城市不同,则写入新的城市名称

               if city != current_city:

                   file.write(f"城市: {city}\n")

                   current_city = city

               # 提取天气数据

               date = data['日期']

               weather = data['天气情况']

               low_temp = data['最低温度']

               high_temp = data['最高温度']

               wind = data['风向']

               level = data['等级']

               # 将天气数据写入文件

               file.write(f"日期:{date:<10}天气情况:{weather:<9}最低温度:{low_temp:<9}最高温度:{high_temp:<9}风向:{wind:<15}等级:{level:<6}\n")

       # 打印消息,表示数据已经写入文件

       print(f"Data written to {filename}")

   except Exception as e:

       # 如果在写入文件过程中发生错误,打印错误消息

       print(f"Error occurred while writing to file: {e}")

# 主函数,获取安徽省所有城市的天气数据,并写入文件

def main():

   try:

       AnHui_area_ids = get_AnHui_areaid()

       all_weather_data = []

       for area_id in AnHui_area_ids:

           url = f"http://www.weather.com.cn/weather/{area_id}.shtml"

           weather_data = get_weather_data(url)

           if weather_data and weather_data[0]['城市'] not in [data['城市'] for data in all_weather_data]:

               all_weather_data.extend(weather_data)

       write_to_file(all_weather_data)

   except Exception as e:

       print(f"An error occurred: {e}")

# 如果直接运行这个文件,就执行main函数

if __name__ == "__main__":

   main()