翼度科技»论坛 编程开发 python 查看内容

urllib+BeautifulSoup爬取并解析2345天气王历史天气数据

3

主题

3

帖子

9

积分

新手上路

Rank: 1

积分
9
urllib+BeautifulSoup爬取并解析2345天气王历史天气数据
网址:东城历史天气查询_历史天气预报查询_2345天气预报

1、代码
  1. import json
  2. import logging
  3. import urllib.parse
  4. from datetime import date, datetime
  5. from random import randint
  6. from time import sleep
  7. import pymysql
  8. from bs4 import BeautifulSoup
  9. # 定义目标URL
  10. import requests
  11. def weather_req():
  12.     month_list = [1,2,3,4,5,6]  # 月份
  13.     code_list = get_code()  # 获取所有的 天气code 和 地区code
  14.     # 需要 2018 1月 到 2023 6月
  15.     url = "https://tianqi.2345.com/Pc/GetHistory"   # 原始URL
  16.     full_url = ""   # 最终拼好的url
  17.     # 定义请求头
  18.     headers = {
  19.         'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.58',
  20.     }
  21.     # 定义GET参数
  22.     params = {
  23.         'areaInfo[areaId]': 70809,
  24.         'areaInfo[areaType]': 2,
  25.         'date[year]': 2023,
  26.         'date[month]': 6
  27.     }
  28.     # 遍历 天气code 和 地区code 的列表
  29.     for code_item in code_list:
  30.         weather_code = code_item[0] # 拿到天气code
  31.         area_code = code_item[1]    # 拿到地区code
  32.         # 修改 url 参数 天气code的值
  33.         params['areaInfo[areaId]'] = weather_code
  34.         # 开始遍历月份列表
  35.         for month_item in month_list:
  36.             print(f"正在爬取天气ID为【{weather_code}】,地区ID为【{area_code}】的第【{month_item}】月的数据!")
  37.             # 修改 month 的值为新值
  38.             params['date[month]'] = month_item
  39.             # 编码 GET参数
  40.             encoded_params = urllib.parse.urlencode(params)
  41.             # 拼接完整的URL
  42.             full_url = url + '?' + encoded_params
  43.             print(full_url)
  44.             try:
  45.                 sleep(randint(1, 3))    # 睡眠(随机1-3秒)
  46.                 # 发起请求
  47.                 res = requests.get(full_url, headers=headers)
  48.                 res_data = json.loads(res.text)
  49.                 weather_data = res_data['data']
  50.                 # print(weather_data)
  51.                 # 解析数据
  52.                 soup = BeautifulSoup(weather_data, 'html.parser')
  53.                 # 拿到需要的table
  54.                 table_data = soup.find('table', attrs={'class': 'history-table'})
  55.                 # print(type(table_data),'\n',table_data)
  56.                 all_tr = table_data.find_all('tr')  # 拿到所有的tr
  57.                 # print(all_tr[0])
  58.                 weather_list = []   # 这是要存储数据的list
  59.                 # 开始遍历tr列表 一个列表存储了某地区的某年份的某月完整的数据
  60.                 for i in range(1, len(all_tr)):
  61.                     temp_list = []  # 暂时存储一天的数据 每次循环都刷新
  62.                     tr_item = all_tr[i] # 拿到一个tr数据
  63.                     all_td = tr_item.find_all("td") # 拿到一个tr里的所有td,td里面的text就是需要的值
  64.                     rdate = str(all_td[0].text)  # 日期 2023-01-01 周日
  65.                     # 日期需要转化格式,去掉星期
  66.                     rdate_new = rdate.split(" ")[0] # 拿到日期字符串
  67.                     # 解析字符串为日期对象
  68.                     date_object = datetime.strptime(rdate_new, "%Y-%m-%d")
  69.                     # 将日期对象格式化为 MySQL 可存储的日期字符串
  70.                     mysql_date = date_object.strftime("%Y-%m-%d")   # 最终被存储的日期
  71.                     wind_and_power = all_td[4].text # 风向和风力是在一起的 需要解析
  72.                     wind = str(wind_and_power).split("风")[0]    # 风向
  73.                     winp = str(wind_and_power).split("风")[1]   # 风力
  74.                     temp_max = str(all_td[1].text)  # 最高温
  75.                     temp_min = str(all_td[2].text)  # 最低温
  76.                     weather = str(all_td[3].text)   # 天气情况
  77.                     # 把上面的变量存储到 temp_list 然后再一起存到 weather_list
  78.                     temp_list.append(mysql_date)    # 日期
  79.                     temp_list.append(weather_code)  # 天气编码
  80.                     temp_list.append(area_code) # 地区编码
  81.                     temp_list.append(wind)  # 风向
  82.                     temp_list.append(winp) # 风力
  83.                     temp_list.append(temp_max)  # 最高温度
  84.                     temp_list.append(temp_min)  # 最低温度
  85.                     temp_list.append(weather)   # 天气情况
  86.                     weather_list.append(temp_list)
  87.                 print(weather_list)
  88.                 # 开始插入数据 【某个地区的,某一年的,某一个月份的数据】
  89.                 conn_his,cursor_his = get_conn()    # 建立数据库连接
  90.                 # 遍历数据
  91.                 for save_item in weather_list:
  92.                     INSERT_SQL = "insert into w_weather_day_history (rdate,weather_code,area_code,wind,winp,temp_max,temp_min,weather) " \
  93.                                  "values(%s,%s,%s,%s,%s,%s,%s,%s)" \
  94.                                  "              "%("""+save_item[0]+""",
  95.                                                   """+save_item[1]+""",
  96.                                                   """+save_item[2]+""",
  97.                                                   """+save_item[3]+"""
  98.                                                  ,"""+save_item[4]+"""
  99.                                                  ,"""+save_item[5]+"""
  100.                                                  ,"""+save_item[6]+"""
  101.                                                  ,"""+save_item[7]+""")
  102.                     print(INSERT_SQL)
  103.                     cursor_his.execute(INSERT_SQL)  # 执行sql语句
  104.                     conn_his.commit()  # 提交事务
  105.                     print("--------------------------------------------------")
  106.             except urllib.error.URLError as e:
  107.                 print("发生错误:", e)
  108. def get_code():
  109.     conn,cursor = get_conn()
  110.     SQL = "select fwc.weather_code,fwc.area_code from f_weather_area_code fwc;"
  111.     cursor.execute(SQL)
  112.     res = cursor.fetchall()
  113.     print(res)
  114.     return res
  115. def get_conn():
  116.     """
  117.     :return: 连接,游标
  118.     """
  119.     # 创建连接
  120.     conn = pymysql.connect(host="127.0.0.1",
  121.                     user="root",
  122.                     password="reliable",
  123.                     db="weather",
  124.                     charset="utf8")
  125.     # 创建游标
  126.     cursor = conn.cursor()  # 执行完毕返回的结果集默认以元组显示
  127.     return conn, cursor
  128. def close_conn(conn, cursor):
  129.     if cursor:
  130.         cursor.close()
  131.     if conn:
  132.         conn.close()
  133. if __name__ == '__main__':
  134.     # get_code()
  135.     weather_req()
复制代码

2、分析

url构成如下:
基础url:https://tianqi.2345.com/Pc/GetHistory
参数:
  1. params = {
  2.         'areaInfo[areaId]': 70809,
  3.         'areaInfo[areaType]': 2,
  4.         'date[year]': 2023,
  5.         'date[month]': 6
  6.     }
复制代码
areaInfo[areaId] 表示的是 某地区的天气编码,这个需要去自己获取。
areaInfo[areaType] 不用管
后面两个参数就是年份和月份了
3、发起请求demo
  1. url = "https://tianqi.2345.com/Pc/GetHistory"   # 原始URL    full_url = ""   # 最终拼好的url    # 定义请求头    headers = {        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.58',    }    # 定义GET参数    params = {
  2.         'areaInfo[areaId]': 70809,
  3.         'areaInfo[areaType]': 2,
  4.         'date[year]': 2023,
  5.         'date[month]': 6
  6.     }        # 解析参数    encoded_params = urllib.parse.urlencode(params)    # 拼接完整的URL    full_url = url + '?' + encoded_params    sleep(randint(1, 3))    # 睡眠(随机1-3秒)    # 发起请求    res = requests.get(full_url, headers=headers)    res_data = json.loads(res.text)    weather_data = res_data['data']
复制代码
4、解析数据demo
  1. # 解析数据
  2. soup = BeautifulSoup(weather_data, 'html.parser')
  3. # 拿到需要的table
  4. table_data = soup.find('table', attrs={'class': 'history-table'})
  5. # print(type(table_data),'\n',table_data)
  6. all_tr = table_data.find_all('tr')  # 拿到所有的tr
复制代码
来源:https://www.cnblogs.com/rainbow-1/p/17520928.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具