urllib+BeautifulSoup爬取並解析2345天氣王歷史天氣數據

来源:https://www.cnblogs.com/rainbow-1/archive/2023/07/02/17520928.html
-Advertisement-
Play Games

urllib+BeautifulSoup爬取並解析2345天氣王歷史天氣數據 網址:[東城歷史天氣查詢_歷史天氣預報查詢_2345天氣預報](https://tianqi.2345.com/wea_history/71445.htm) ![image-20230702161423470](https ...


urllib+BeautifulSoup爬取並解析2345天氣王歷史天氣數據


網址:東城歷史天氣查詢_歷史天氣預報查詢_2345天氣預報

image-20230702161423470

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 = json.loads(res.text)
                weather_data = res_data['data']
                # print(weather_data)
                # 解析數據
                soup = BeautifulSoup(weather_data, 'html.parser')
                # 拿到需要的table
                table_data = 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()

image-20230702161542526

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 = json.loads(res.text)
    weather_data = res_data['data']

4、解析數據demo

# 解析數據
soup = BeautifulSoup(weather_data, 'html.parser')
# 拿到需要的table
table_data = 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博客

更多分享盡在我的訂閱號:靠譜楊的挨踢生活


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • # Linux grep、sed、awk(包含練習題) ## 一、grep Linux grep (global regular expression) 命令用於查找文件里符合條件的字元串或正則表達式。 1. 基本用法與常見的正則表達式 > ``` > grep [options] pattern ...
  • 前幾天說明瞭Windows Powershell的使用方法,本來以為這就是適合自己的小工具了,沒想到狠狠打了自己的臉,不能夠顯示圖形化界面。(pavucontrol命令會顯示圖形化音量設置選項) 而且在網上沒找到相應的解決辦法,有知道的大佬們可以在評論區指個路子,萬分感謝。 自己沒有辦法,於是就從以 ...
  • Oracle能夠讓你在無須修改非Null值數據的情況下方便地把Null值排到最前面或者最後面,其他資料庫得添加一個輔助列 ...
  • 本文以 `React`、`Vue` 為例,介紹下主流的渲染模式以及在主流框架中如何實現上述的渲染模式。 ## 前置知識介紹 看渲染模式之前我們先看下幾個主流框架所提供的相關能力,瞭解的可跳到下個章節。 ### 掛載組件到 DOM 節點 這是主流框架最基本的能力,就是將組件渲染到指定的 `DOM` 節 ...
  • 關鍵字 abstractassertbooleanbreakbyte case catch char class const continue default do double else enum extends final finally float for goto if implementi ...
  • 不說廢話,直接上乾貨: (註意大小寫:object為對象,Object為類) 1,object.getClass()它是Object類的實例方法,返回一個對象運行時的類的Class對象,換句話說,它返回的是對象具體類型的類對象。 2,Object.class 這是java語言的一種語法糖,用來返回一 ...
  • # 前言 最近針對java項目的部署方式進行整理,jenkins/tomcat/windows工具/linux腳本/web部署平臺等等 發現war包通過tomcat部署比較繁瑣,等待時間長,配置規則複雜對於小白很不友好,也難以接入到自定義的部署工具/平臺中 之前開發的Jar包部署平臺是servlet ...
  • 數組索引是指在`numpy`數組中引用特定元素的方法。`numpy`的數組索引又稱為`fancy indexing`,比其他編程語言的索引強大很多。 # 1. 選取數據 numpy的索引除了像其他語言一樣選擇一個元素,還可以間隔著選取多個元素,也可以用任意的順序選取元素。 比如一維數組: ```py ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...