Gitee作業連結:https://gitee.com/zheng-qijian33/crawl_project/tree/master/作業2
作業①
要求:在中國氣象網(http://www.weather.com.cn)給定城市集的7日天氣預報,並儲存在資料庫
程式碼
import requests
import sqlite3
from bs4 import BeautifulSoup
import logging
# 配置日誌記錄
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
# 獲取指定城市的天氣資料
def fetch_weather_data(city_code):
base_url = 'http://www.weather.com.cn/weather/'
full_url = f'{base_url}{city_code}.shtml'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 SLBrowser/9.0.3.5211 SLBChan/112'
}
try:
response = requests.get(full_url, headers=headers)
response.raise_for_status()
response.encoding = 'utf-8'
soup = BeautifulSoup(response.text, 'html.parser')
weather_forecast = []
forecast_list = soup.find('ul', class_='t clearfix').find_all('li')
for day in forecast_list:
date = day.find('h1').text.strip()
weather = day.find('p', class_='wea').text.strip()
temp_high = day.find('span').text.strip() if day.find('span') else ''
temp_low = day.find('i').text.strip()
temp = f"{temp_high}/{temp_low}"
weather_forecast.append((date, weather, temp))
return weather_forecast
except requests.RequestException as e:
logging.error(f"Error fetching weather data for city code {city_code}: {e}")
return []
# 建立資料庫和表
def setup_database():
conn = sqlite3.connect('weathers.db')
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS weather_forecast (
id INTEGER PRIMARY KEY AUTOINCREMENT,
city TEXT,
date TEXT,
weather TEXT,
temperature TEXT
)
''')
conn.commit()
return conn
# 儲存天氣資料到資料庫
def save_weather_data(city, weather_data, conn):
cursor = conn.cursor()
for date, weather, temp in weather_data:
cursor.execute("INSERT INTO weather_forecast (city, date, weather, temperature) VALUES (?, ?, ?, ?)",
(city, date, weather, temp))
conn.commit()
# 顯示資料庫中的天氣資料
def display_weather_data(conn):
cursor = conn.cursor()
cursor.execute("SELECT * FROM weather_forecast")
rows = cursor.fetchall()
print(f"{'序號':<5} {'地區':<10} {'日期':<15} {'天氣資訊':<20} {'溫度':<15}")
for row in rows:
print(f"{row[0]:<5} {row[1]:<10} {row[2]:<15} {row[3]:<20} {row[4]:<15}")
def main():
# 定義城市和對應的程式碼
city_codes = {
'北京': '101010100',
'上海': '101020100',
'福州': '101230101',
'天津': '101030100'
}
# 建立資料庫連線
conn = setup_database()
# 獲取並儲存每個城市的天氣資料
for city, city_code in city_codes.items():
weather_data = fetch_weather_data(city_code)
if weather_data:
save_weather_data(city, weather_data, conn)
else:
logging.warning(f"No weather data for city {city}")
# 顯示資料庫中的天氣資料
display_weather_data(conn)
conn.close()
if __name__ == '__main__':
main()
執行結果
心得體會
編寫這段天氣資料抓取和儲存的程式碼讓我深刻體會到,良好的程式設計實踐如模組化設計、錯誤處理、日誌記錄和資料驗證對於構建健壯、可維護的應用程式至關重要。模組化設計使得程式碼更易於理解和擴充套件;錯誤處理確保了程式在面對異常情況時能夠優雅地響應;日誌記錄為監控和除錯提供了寶貴的資訊;資料驗證則保障了資料的準確性和完整性。
作業②
要求:用requests和BeautifulSoup庫方法定向爬取股票相關資訊,並儲存在資料庫中。
程式碼
import requests
import re
import sqlite3
# 用get方法訪問伺服器並提取頁面資料
def getHtml(page,cmd):
url = ("http://66.push2.eastmoney.com/api/qt/clist/get?cb=jQuery112409097606620255823_1696662149317&pn=1&pz=20&po=1&np="+str(page)+
"&ut=bd1d9ddb04089700cf9c27f6f7426281&fltt=2&invt=2&wbp2u=|0|0|0|web&"+cmd+
"&fields=f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f12,f13,f14,f15,f16,f17,f18,f20,f21,f23,f24,f25,f22,f11,f62,f128,f136,f115,f152&_=1696662149318")
r = requests.get(url)
pat = "\"diff\":\\[(.*?)\\]"
data = re.compile(pat, re.S).findall(r.text)
return data
def getOnePageStock(cmd, page):
# 提供的JSON陣列
data = getHtml(page,cmd)
datas = data[0].split("},")
#分解每條股票
# 連線到SQLite資料庫(如果不存在,則會建立一個新的資料庫檔案)
conn = sqlite3.connect('stock_data.db')
cursor = conn.cursor()
# 建立股票資訊表
cursor.execute('''CREATE TABLE IF NOT EXISTS stock_info (
id INTEGER PRIMARY KEY,
stock_code TEXT,
stock_name TEXT,
stock_price REAL,
price_change REAL,
price_change_percent REAL,
volume INTEGER,
turnover REAL,
amplitude REAL,
highest REAL,
lowest REAL,
open_price REAL,
last_close REAL
)''')
# 解析JSON陣列並將資料儲存到資料庫中
for item in datas:
# 使用字串操作來提取鍵值對
stock_info = {}
pairs = item.split(',')
for pair in pairs:
key, value = pair.split(':')
key = key.strip('"')
value = value.strip('"')
stock_info[key] = value
# 提取需要的欄位
stock_code = stock_info.get('f12', 'N/A')
stock_name = stock_info.get('f14', 'N/A')
stock_price = float(stock_info.get('f2', 0.0))
price_change_percent = float(stock_info.get('f3', 0.0))
price_change = float(stock_info.get('f4', 0.0))
volume = int(stock_info.get('f5', 0))
turnover = float(stock_info.get('f6', 0.0))
amplitude = float(stock_info.get('f7', 0.0))
highest = float(stock_info.get('f15', 0.0))
lowest = float(stock_info.get('f16', 0.0))
open_price = float(stock_info.get('f17', 0.0))
last_close = float(stock_info.get('f18', 0.0))
# 插入資料到資料庫中
cursor.execute(
"INSERT INTO stock_info (stock_code, stock_name, stock_price, price_change_percent, price_change, volume, turnover, amplitude, highest, lowest, open_price, last_close) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
(stock_code, stock_name, stock_price, price_change_percent, price_change, volume, turnover, amplitude, highest,
lowest, open_price, last_close))
conn.commit()
# 查詢股票資訊
cursor.execute("SELECT * FROM stock_info")
# 獲取查詢結果
stocks = cursor.fetchall()
# 獲取查詢結果的列名
columns = [desc[0] for desc in cursor.description]
# 列印列標籤
print("\t".join(columns))
# 列印股票資訊
for stock in stocks:
# 列印每行資料
print("\t".join(map(str, stock)))
# 關閉資料庫連線
conn.close()
page = 1
getOnePageStock("fid=f3&fs=m:0+t:6,m:0+t:80,m:1+t:2,m:1+t:23,m:0+t:81+s:2048", page)
執行結果
心得體會
在編寫這段程式碼的過程中,我深刻體會到了網路資料抓取和解析的複雜性與挑戰性。首先,透過使用谷歌瀏覽器的F12除錯工具,我學會了如何監控網路請求,識別出股票資料載入時使用的具體API端點。這一步對於理解資料來源和結構至關重要。
分析API返回的JSON資料讓我意識到,資料的結構化和非結構化部分需要仔細處理。透過使用正規表示式和字串操作,我能夠提取出所需的關鍵資訊,並將其組織成適合儲存和查詢的格式。
在編寫程式碼時,我意識到請求引數的選擇對於獲取正確的資料至關重要。透過調整URL中的引數,如f1和f2,我能夠控制返回的資料範圍和內容。這種靈活性使我能夠根據需求定製資料抓取任務,提高了效率和準確性。
作業③
要求:爬取中國大學2021主榜(https://www.shanghairanking.cn/rankings/bcur/2021)所有院校資訊,並儲存在資料庫中,同時將瀏覽器F12除錯分析的過程錄製Gif加入至部落格中。
程式碼
import urllib.request
from bs4 import BeautifulSoup
import sqlite3
# 目標網頁URL
your_url = 'https://www.shanghairanking.cn/rankings/bcur/2021'
# 使用 urllib 開啟網頁
response = urllib.request.urlopen(your_url)
html = response.read()
# 使用 BeautifulSoup 解析網頁
soup = BeautifulSoup(html, 'html.parser')
# 定位到包含大學排名資訊的部分
table = soup.find('table', {'class': 'rk-table'})
# 連線到SQLite資料庫(如果資料庫不存在則建立)
conn = sqlite3.connect('schools_rank.db')
cursor = conn.cursor()
# 建立表(如果尚未建立)
cursor.execute('''CREATE TABLE IF NOT EXISTS university_ranking
(rank TEXT, school_name TEXT, province_city TEXT, school_type TEXT, total_score TEXT)''')
# 遍歷表格中的每一行
for row in table.find_all('tr')[1:]: # 跳過表頭
cols = row.find_all('td')
rank = cols[0].text.strip()
school_name = cols[1].text.strip()
province_city = cols[2].text.strip()
school_type = cols[3].text.strip()
total_score = cols[4].text.strip()
# 插入資料到資料庫
cursor.execute('''INSERT INTO university_ranking (rank, school_name, province_city, school_type, total_score)
VALUES (?, ?, ?, ?, ?)''', (rank, school_name, province_city, school_type, total_score))
# 提交事務
conn.commit()
# 查詢資料庫並列印所有記錄
cursor.execute("SELECT * FROM university_ranking")
all_records = cursor.fetchall()
for record in all_records:
# 移除字串中的換行符
cleaned_record = tuple(field.replace('\n', '') for field in record)
# 列印清理後的記錄
print(cleaned_record)
# 關閉資料庫連線
conn.close()
print("大學排名資料已儲存到資料庫")
執行結果
瀏覽器F12除錯分析的過程錄製Gif
心得體會
編寫這段程式碼的過程中,我深刻體會到了網路資料抓取和解析的複雜性與挑戰性。首先,透過分析目標網站的網路請求,我學會了如何識別和理解網站載入資料時使用的API端點。這一步對於理解資料的來源和結構至關重要。
在分析API返回的資料時,我意識到資料的結構化和非結構化部分需要仔細處理。透過使用BeautifulSoup庫,我能夠解析HTML內容並提取出所需的關鍵資訊,如大學排名、學校名稱、所在城市、學校型別和總分。
將資料儲存到SQLite資料庫中的過程讓我認識到了資料持久化的重要性。透過建立表和插入資料,我確保了抓取到的資訊可以被長期儲存和查詢,這對於後續的資料分析和應用是非常有用的。