urllib+BeautifulSoup爬取并決議2345天氣王歷史天氣資料
網址:東城歷史天氣查詢_歷史天氣預報查詢_2345天氣預報

1、代碼
import json
import logging
import urllib.parse
from datetime import date, datetime
from random import randint
from time import sleep
import pymysql
from bs4 import BeautifulSoup
# 定義目標URL
import requests
def weather_req():
month_list = [1,2,3,4,5,6] # 月份
code_list = get_code() # 獲取所有的 天氣code 和 地區code
# 需要 2018 1月 到 2023 6月
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 = {
'areaInfo[areaId]': 70809,
'areaInfo[areaType]': 2,
'date[year]': 2023,
'date[month]': 6
}
# 遍歷 天氣code 和 地區code 的串列
for code_item in code_list:
weather_code = code_item[0] # 拿到天氣code
area_code = code_item[1] # 拿到地區code
# 修改 url 引數 天氣code的值
params['areaInfo[areaId]'] = weather_code
# 開始遍歷月份串列
for month_item in month_list:
print(f"正在爬取天氣ID為【{weather_code}】,地區ID為【{area_code}】的第【{month_item}】月的資料!")
# 修改 month 的值為新值
params['date[month]'] = month_item
# 編碼 GET引數
encoded_params = urllib.parse.urlencode(params)
# 拼接完整的URL
full_url = url + '?' + encoded_params
print(full_url)
try:
sleep(randint(1, 3)) # 睡眠(隨機1-3秒)
# 發起請求
res = requests.get(full_url, headers=headers)
res_data = https://www.cnblogs.com/rainbow-1/archive/2023/07/02/json.loads(res.text)
weather_data = res_data['data']
# print(weather_data)
# 決議資料
soup = BeautifulSoup(weather_data, 'html.parser')
# 拿到需要的table
table_data = https://www.cnblogs.com/rainbow-1/archive/2023/07/02/soup.find('table', attrs={'class': 'history-table'})
# print(type(table_data),'\n',table_data)
all_tr = table_data.find_all('tr') # 拿到所有的tr
# print(all_tr[0])
weather_list = [] # 這是要存盤資料的list
# 開始遍歷tr串列 一個串列存盤了某地區的某年份的某月完整的資料
for i in range(1, len(all_tr)):
temp_list = [] # 暫時存盤一天的資料 每次回圈都重繪
tr_item = all_tr[i] # 拿到一個tr資料
all_td = tr_item.find_all("td") # 拿到一個tr里的所有td,td里面的text就是需要的值
rdate = str(all_td[0].text) # 日期 2023-01-01 周日
# 日期需要轉化格式,去掉星期
rdate_new = rdate.split(" ")[0] # 拿到日期字串
# 決議字串為日期物件
date_object = datetime.strptime(rdate_new, "%Y-%m-%d")
# 將日期物件格式化為 MySQL 可存盤的日期字串
mysql_date = date_object.strftime("%Y-%m-%d") # 最終被存盤的日期
wind_and_power = all_td[4].text # 風向和風力是在一起的 需要決議
wind = str(wind_and_power).split("風")[0] # 風向
winp = str(wind_and_power).split("風")[1] # 風力
temp_max = str(all_td[1].text) # 最高溫
temp_min = str(all_td[2].text) # 最低溫
weather = str(all_td[3].text) # 天氣情況
# 把上面的變數存盤到 temp_list 然后再一起存到 weather_list
temp_list.append(mysql_date) # 日期
temp_list.append(weather_code) # 天氣編碼
temp_list.append(area_code) # 地區編碼
temp_list.append(wind) # 風向
temp_list.append(winp) # 風力
temp_list.append(temp_max) # 最高溫度
temp_list.append(temp_min) # 最低溫度
temp_list.append(weather) # 天氣情況
weather_list.append(temp_list)
print(weather_list)
# 開始插入資料 【某個地區的,某一年的,某一個月份的資料】
conn_his,cursor_his = get_conn() # 建立資料庫連接
# 遍歷資料
for save_item in weather_list:
INSERT_SQL = "insert into w_weather_day_history (rdate,weather_code,area_code,wind,winp,temp_max,temp_min,weather) " \
"values(%s,%s,%s,%s,%s,%s,%s,%s)" \
" "%("\""+save_item[0]+"\"",
"\""+save_item[1]+"\"",
"\""+save_item[2]+"\"",
"\""+save_item[3]+"\""
,"\""+save_item[4]+"\""
,"\""+save_item[5]+"\""
,"\""+save_item[6]+"\""
,"\""+save_item[7]+"\"")
print(INSERT_SQL)
cursor_his.execute(INSERT_SQL) # 執行sql陳述句
conn_his.commit() # 提交事務
print("--------------------------------------------------")
except urllib.error.URLError as e:
print("發生錯誤:", e)
def get_code():
conn,cursor = get_conn()
SQL = "select fwc.weather_code,fwc.area_code from f_weather_area_code fwc;"
cursor.execute(SQL)
res = cursor.fetchall()
print(res)
return res
def get_conn():
"""
:return: 連接,游標
"""
# 創建連接
conn = pymysql.connect(host="127.0.0.1",
user="root",
password="reliable",
db="weather",
charset="utf8")
# 創建游標
cursor = conn.cursor() # 執行完畢回傳的結果集默認以元組顯示
return conn, cursor
def close_conn(conn, cursor):
if cursor:
cursor.close()
if conn:
conn.close()
if __name__ == '__main__':
# get_code()
weather_req()

2、分析
url構成如下:
基礎url:https://tianqi.2345.com/Pc/GetHistory
引數:
params = {
'areaInfo[areaId]': 70809,
'areaInfo[areaType]': 2,
'date[year]': 2023,
'date[month]': 6
}
areaInfo[areaId] 表示的是 某地區的天氣編碼,這個需要去自己獲取,
areaInfo[areaType] 不用管
后面兩個引數就是年份和月份了
3、發起請求demo
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 = {
'areaInfo[areaId]': 70809,
'areaInfo[areaType]': 2,
'date[year]': 2023,
'date[month]': 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 = https://www.cnblogs.com/rainbow-1/archive/2023/07/02/json.loads(res.text)
weather_data = res_data['data']
4、決議資料demo
# 決議資料
soup = BeautifulSoup(weather_data, 'html.parser')
# 拿到需要的table
table_data = https://www.cnblogs.com/rainbow-1/archive/2023/07/02/soup.find('table', attrs={'class': 'history-table'})
# print(type(table_data),'\n',table_data)
all_tr = table_data.find_all('tr') # 拿到所有的tr
好看請贊,養成習慣:) 本文來自博客園,作者:靠譜楊, 轉載請注明原文鏈接:https://www.cnblogs.com/rainbow-1/p/17520928.html
關于筆者: 我的主頁
歡迎來我的51CTO主頁踩一踩~ 我的51CTO博客
更多分享盡在我的訂閱號:靠譜楊的挨踢生活
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/556490.html
標籤:其他
下一篇:返回列表
