資料採集作業二

早八打酱油發表於2024-10-21

資料採集作業二

課程連結 https://edu.cnblogs.com/campus/fzu/2024DataCollectionandFusiontechnology
作業連結 https://edu.cnblogs.com/campus/fzu/2024DataCollectionandFusiontechnology/homework/13285
作業連結 https://gitee.com/jsjdjjdjajsd/getinformation/tree/master/作業二
學號姓名 102202119吳佳輝

作業1

1.資料採集實驗
要求:在中國氣象網(http://www.weather.com.cn)給定城市集的 7日天氣預報,並儲存在資料庫。

點選檢視程式碼
from bs4 import BeautifulSoup
from bs4.dammit import UnicodeDammit
import urllib.request
import mysql.connector

class WeatherDB:
    def __init__(self):
        self.cursor = None
        self.con = None

    def openDB(self):
        self.con = mysql.connector.connect(
            host="localhost",
            user="root",
            password="123456",
            database="weather_db"
        )
        self.cursor = self.con.cursor()
        try:
            self.cursor.execute(
                "CREATE TABLE IF NOT EXISTS weathers (wCity VARCHAR(16), wDate VARCHAR(16), wWeather VARCHAR(64), wTemp VARCHAR(32), PRIMARY KEY (wCity, wDate))"
            )
        except Exception as err:
            print(err)

    def closeDB(self):
        self.con.commit()
        self.con.close()

    def insert(self, city, date, weather, temp):
        try:
            self.cursor.execute(
                "INSERT INTO weathers (wCity, wDate, wWeather, wTemp) VALUES (%s, %s, %s, %s)",
                (city, date, weather, temp)
            )
        except Exception as err:
            print(err)

    def show(self):
        self.cursor.execute("SELECT * FROM weathers")
        rows = self.cursor.fetchall()
        print("%-16s%-16s%-32s%-16s" % ("city", "date", "weather", "temp"))
        for row in rows:
            print("%-16s%-16s%-32s%-16s" % (row[0], row[1], row[2], row[3]))

class WeatherForecast:
    def __init__(self):
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Windows; U; Windows NT 6.0 x64; en-US; rv:1.9pre) Gecko/2008072421 Minefield/3.0.2pre"
        }
        self.cityCode = {"鄭州": "101180101", "銀川": "101170101", "福州": "101230101", "北京": "101010100"}

    def forecastCity(self, city):
        if city not in self.cityCode.keys():
            print(city + " 找不到程式碼")
            return
        url = "http://www.weather.com.cn/weather/" + self.cityCode[city] + ".shtml"
        try:
            req = urllib.request.Request(url, headers=self.headers)
            data = urllib.request.urlopen(req)
            data = data.read()
            dammit = UnicodeDammit(data, ["utf-8", "gbk"])
            data = dammit.unicode_markup
            soup = BeautifulSoup(data, "lxml")
            lis = soup.select("ul[class='t clearfix'] li")
            x = 0
            for li in lis:
                try:
                    date = li.select('h1')[0].text
                    weather = li.select('p[class="wea"]')[0].text
                    if x == 0:
                        x += 1
                        temp = li.select('p[class="tem"] i')[0].text
                    else:
                        temp = li.select('p[class="tem"] span')[0].text + "/" + li.select('p[class="tem"] i')[0].text
                    print(city, date, weather, temp)
                    self.db.insert(city, date, weather, temp)
                except Exception as err:
                    print(err)
        except Exception as err:
            print(err)

    def process(self, cities):
        self.db = WeatherDB()
        self.db.openDB()
        for city in cities:
            self.forecastCity(city)
        self.db.closeDB()

ws = WeatherForecast()
ws.process(["鄭州", "銀川", "福州", "北京"])
print("completed")

執行結果在mysql資料庫檢視
image

心得體會

在編寫這段天氣預報程式的過程中,我對Python在網路爬蟲和資料庫互動方面的應用有了更深的理解。透過使用BeautifulSoup庫解析HTML文件,我掌握瞭如何提取網頁中的特定資訊,比如天氣、日期和溫度。這讓我意識到,雖然獲取資訊的過程可能會受到頁面結構變化的影響,但靈活運用選擇器和異常處理可以有效提高程式碼的魯棒性。
此外,使用mysql.connector與MySQL資料庫進行互動讓我體會到資料持久化的重要性。在這段程式碼中,我建立了一個資料庫來儲存天氣資訊,這樣不僅可以方便後續查詢,也為資料分析打下了基礎。透過封裝成WeatherDB類,我能夠更好地管理資料庫的連線和操作,體現了物件導向程式設計的優勢。
在異常處理方面,程式碼中透過try-except結構來捕獲可能出現的錯誤,這增強了程式的穩定性,避免了因意外情況導致的程式崩潰。此外,使用使用者代理字串來模擬瀏覽器請求,有效地避免了因爬蟲檢測而導致的訪問限制。
總的來說,這段程式碼不僅是對技術的實踐,也是對程式設計思維的培養。讓我在實際專案中學習到了如何將不同模組結合在一起,從而實現複雜的功能。透過這次實踐,我對爬蟲技術和資料庫操作的理解更加深入,也激發了我對資料分析和應用開發的興趣。

作業二

1.資料採集實驗
要求:用 requests 和 BeautifulSoup 庫方法定向爬取股票相關資訊,並儲存在資料庫中。
候選網站:東方財富網:https://www.eastmoney.com/ 新浪股票:http://finance.sina.com.cn/stock/

點選檢視程式碼
import requests
import mysql.connector
import json

db_config = {
    'user': 'root',
    'password': '123456',
    'host': 'localhost',
    'database': 'stock_db'
}

conn = mysql.connector.connect(**db_config)
c = conn.cursor()

c.execute('''
    CREATE TABLE IF NOT EXISTS stock_data (
        id INT AUTO_INCREMENT PRIMARY KEY,
        stock_code VARCHAR(10),
        stock_name VARCHAR(50),
        current_price DECIMAL(10, 2),
        change_percent DECIMAL(5, 2),
        change_amount DECIMAL(10, 2)
    )
''')

url = "http://push2.eastmoney.com/api/qt/clist/get"
params = {
    "pn": "1",
    "pz": "20",
    "po": "1",
    "np": "1",
    "ut": "bd1d9ddb04089700cf9c27f6f7426281",
    "fltt": "2",
    "invt": "2",
    "fid": "f3",
    "fs": "m:0+t:6",
    "fields": "f1,f2,f3,f4,f12,f14"
}
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
}

response = requests.get(url, params=params, headers=headers)
data = response.json()

if data and data['data']:
    stock_list = data['data']['diff']
    stock_data = []
    for stock in stock_list:
        stock_code = stock['f12']
        stock_name = stock['f14']
        current_price = stock['f2']
        change_percent = stock['f3']
        change_amount = stock['f4']
        stock_data.append((stock_code, stock_name, current_price, change_percent, change_amount))

    c.executemany('''
        INSERT INTO stock_data (stock_code, stock_name, current_price, change_percent, change_amount) 
        VALUES (%s, %s, %s, %s, %s)
    ''', stock_data)
    conn.commit()
    print("股票資料已成功儲存到資料庫。")

c.close()
conn.close()

心得體會

在編寫這段股票資料爬取並儲存到資料庫的程式碼過程中,我對Python的網路請求和資料庫操作有了更深的理解。首先,透過使用requests庫發起HTTP請求,我成功地從東方財富網獲取了實時的股票資料。這個過程讓我認識到,網路資料爬取的核心在於正確構造請求引數以及處理返回的JSON格式資料。
資料的解析和儲存是我學習的另一個重點。利用json庫將響應資料轉換為Python物件後,我透過遍歷獲取的股票列表,提取了所需的資訊。這一過程中,掌握瞭如何從複雜的資料結構中篩選出關鍵資訊。
在資料庫操作方面,我使用mysql.connector庫連線MySQL資料庫,並建立了一個儲存股票資料的表。透過封裝插入操作的SQL語句,使用executemany方法批次插入資料,這不僅提高了插入效率,也確保了資料的一致性。
此外,我認識到異常處理的重要性,儘管在這段程式碼中沒有加入異常處理,但在實際開發中,考慮網路請求失敗、資料庫連線問題等情況是非常必要的。整體來看,這段程式碼不僅讓我掌握了資料獲取與儲存的基本流程,還激發了我對資料分析和應用開發的濃厚興趣。透過實踐,我更加堅定了在資料科學領域深入探索的決心。

作業三

1.資料採集實驗
要求:爬取中國大學 2021 主榜(https://www.shanghairanking.cn/rankings/bcur/2021)所有院校資訊,並儲存在資料庫中,同時將瀏覽器 F12 除錯分析的過程錄製 Gif 加入至部落格中。

點選檢視程式碼
import requests
import re
import mysql.connector
import logging

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

class DB:
    def open(self):
        try:
            self.connection = mysql.connector.connect(
                host='localhost',
                user='root',
                password='123456',
                database='school_db'
            )
            self.cursor = self.connection.cursor()
            self.cursor.execute(
                'CREATE TABLE IF NOT EXISTS schoolrank ('
                '排行 INT AUTO_INCREMENT PRIMARY KEY, '
                '學校 VARCHAR(16), '
                '省市 VARCHAR(16), '
                '型別 VARCHAR(16), '
                '總分 FLOAT)'
            )
        except mysql.connector.Error as e:
            logging.error(f"Error connecting to database: {e}")

    def close(self):
        try:
            self.connection.commit()
            self.cursor.close()
            self.connection.close()
        except Exception as e:
            logging.error(f"Error closing database connection: {e}")

    def insert(self, name, province, cata, score):
        try:
            score = float(score)
            self.cursor.execute(
                'INSERT INTO schoolrank (學校, 省市, 型別, 總分) VALUES (%s, %s, %s, %s)',
                (name, province, cata, score)
            )
            logging.info(f"Inserted: {name}, {province}, {cata}, {score}")
        except ValueError as ve:
            logging.warning(f"ValueError: {ve} - Invalid score value for {name}. Skipping this entry.")
        except Exception as e:
            logging.error(f"Error inserting data: {e}")

url = r'https://www.shanghairanking.cn/_nuxt/static/1728872418/rankings/bcur/2021/payload.js'
req = requests.get(url)
req.raise_for_status()
req.encoding = req.apparent_encoding
data = req.text

univerCnlist = re.findall('univNameCn:"(.*?)",', data)
provincelist = re.findall('province:(.*?),', data)
univerCategorylist = re.findall('univCategory:(.*?),', data)
scorelist = re.findall('score:(.*?),', data)

logging.info(f"University Count: {len(univerCnlist)}")

func_data_key = data[len('__NUXT_JSONP__("/rankings/bcur/2021", (function('):data.find(')')].split(',')
func_data_value = data[data.rfind('(') + 1:-4].split(',')

mydict = {key: value for key, value in zip(func_data_key, func_data_value)}

name = univerCnlist
province = [mydict[item] for item in provincelist]
cate = [mydict[item] for item in univerCategorylist]

db = DB()
db.open()
for i in range(len(name)):
    db.insert(name[i], province[i], cate[i], scorelist[i])
db.close()

心得體會

在實現這段程式碼的過程中,我對資料抓取和資料庫操作的整體流程有了更深入的理解。首先,透過requests庫向目標URL發起請求,成功獲取了包含大學排名資訊的JavaScript資料。這一部分讓我認識到,HTTP請求和響應的處理是網路資料獲取的基礎。
接著,我使用正規表示式從返回的文字中提取了有用的資料,如大學名稱、省市、型別和分數。這一過程讓我體會到,資料清洗和提取在實際應用中是多麼重要,尤其是在處理不規則的資料格式時。
在資料庫操作方面,我建立了一個資料庫連線並構建了表結構,使用mysql.connector庫進行資料插入。這讓我認識到,資料庫的設計和操作需要與資料的結構緊密結合。在插入資料時,注意到資料型別的轉換,如將分數轉為浮點數,以確保資料的準確性。
此外,設定日誌記錄功能使我能夠實時監控程式的執行狀態,及時捕捉並處理可能出現的異常。這一點對於維護程式碼的穩定性和可除錯性至關重要。
總的來說,這段程式碼的實現不僅提升了我的程式設計技能,還增強了我對資料處理和儲存流程的理解,使我更加期待在資料分析和工程領域的進一步探索。

image

相關文章