作業①
1)在中國氣象網(http://www.weather.com.cn)給定深圳的7日天氣預報,並儲存在資料庫。
a、主要程式碼展示和分析
這個類負責從指定的 URL 抓取天氣預報資料並將其插入到資料庫中
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={"深圳":"101280601"}
- init: 初始化HTTP請求頭(模擬瀏覽器行為),並定義一個城市程式碼字典,將城市名稱對映到其相應的天氣程式碼(此處僅包含深圳)。
def forecastCity(self,city):
if city not in self.cityCode.keys():
print(city+" code cannot be found")
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")
for li in lis:
try:
date=li.select('h1')[0].text
weather=li.select('p[class="wea"]')[0].text
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)
- forecastCity: 獲取指定城市的天氣資料:
- 檢查城市是否在程式碼字典中。
- 構建天氣網站的URL併發起請求。
- 使用UnicodeDammit處理返回的資料,確保其正確解碼。
- 使用BeautifulSoup解析HTML,提取天氣資訊(日期、天氣狀況、溫度)。
- 將提取到的天氣資料插入到資料庫中。
- 在過程中捕獲可能發生的異常並列印錯誤資訊。
這個類負責建立,資料等資料庫運算元據庫
class WeatherDB:
def openDB(self):
self.con=sqlite3.connect("weathers.db")
self.cursor=self.con.cursor()
try:
self.cursor.execute("create table weathers (wCity varchar(16),wDate varchar(16),wWeather varchar(64),wTemp varchar(32),constraint pk_weather primary key (wCity,wDate))")
except:
self.cursor.execute("delete from weathers")
def closeDB(self):
self.con.commit()
self.con.close()
- openDB: 連線到SQLite資料庫,如果表不存在則建立一個名為weathers的表。如果表已存在,則清空表中的資料(delete from weathers)。
- closeDB: 提交資料庫事務並關閉連線。
def insert(self,city,date,weather,temp):
try:
self.cursor.execute("insert into weathers (wCity,wDate,wWeather,wTemp) values (?,?,?,?)" ,(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]))
- insert: 向weathers表中插入一條新的天氣記錄。如果插入失敗,捕獲異常並列印錯誤資訊。
- show: 從weathers表中選擇所有記錄並格式化輸出。
b、輸出資訊
c、Gitee資料夾連結
2)心得體會
- 程式碼結構: 程式碼邏輯清晰,將資料庫操作和資料抓取分開,使得程式碼易於維護。物件導向的設計使得每個類的職責明確。
- 異常處理: 透過 try...except 塊處理異常,增強了程式的健壯性,避免因某個步驟失敗導致整個程式崩潰。
作業②
1)用requests和BeautifulSoup庫方法定向爬取東方財富網:(https://www.eastmoney.com/)股票相關資訊,並儲存在資料庫中
a、主要程式碼展示和分析
這個類負責從指定的 URL 抓取股票資料並將其插入到資料庫中。
class StockGet:
def __init__(self):
self.loginheaders = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Safari/537.36',
}
def GetStock(self):
url="http://6.push2.eastmoney.com/api/qt/clist/get?cb=jQuery112408105779319969169_1634089326282&pn=1&pz=20&po=1&np=1&ut=bd1d9ddb04089700cf9c27f6f7426281&fltt=2&invt=2&fid=f3&fs=m:0+t:6,m:0+t:80,m:1+t:2,m:1+t:23&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&_=1634089326289"
data = getHTMLText(url, self.loginheaders)
td1 = re.findall(r'"f14":(.*?),', data)
# 程式碼
td2 = re.findall(r'"f12":(.*?),', data)
# 最新報價
td3 = re.findall(r'"f2":(.*?),', data)
- init 方法:定義請求頭以模擬瀏覽器訪問,提高請求的成功率。
- GetStock 方法:透過 getHTMLText 函式獲取資料,使用正規表示式提取所需的股票資訊(如名稱、程式碼、價格等)。
- 資料抓取函式 getHTMLText,使用 requests 庫傳送 GET 請求,獲取網頁內容。透過設定超時和編碼來確保請求的可靠性。
將提取到的資料插入到 stockDB 的資料庫中,並呼叫 show 方法顯示結果。
這個類負責資料庫的連線和操作,包括開啟、關閉資料庫,插入資料,以及展示資料庫中的內容
class stockDB:
# 開啟資料庫的方法
def openDB(self):
self.con = sqlite3.connect("stock.db")
self.cursor = self.con.cursor()
try:
self.cursor.execute(
"create table equity (sID varchar(16),sName varchar(64),sPrice varchar(16),sRFExtent varchar(16),sRFQuota varchar(16),sNum varchar(16),sQuota varchar(16),sExtent varchar(16),sHigh varchar(16),sLow varchar(16),sToday varchar(16),sYesterday varchar(16),constraint pk_stock primary key (sID,sName))")
except:
self.cursor.execute("delete from equity")
# 關閉資料庫的方法
def closeDB(self):
self.con.commit()
self.con.close()
# 插入資料的方法
def insert(self, ID, name, price, RFextent, RFquota, num, quota, extent, high, low, today, yesterday):
try:
self.cursor.execute(
"insert into equity (sID,sName,sPrice,sRFExtent,sRFQuota,sNum,sQuota,sExtent,sHigh,sLow,sToday,sYesterday) values (?,?,?,?,?,?,?,?,?,?,?,?)",
(ID, name, price, RFextent, RFquota, num, quota, extent, high, low, today, yesterday))
except Exception as err:
print(err)
# 列印資料庫內容的方法
def show(self):
self.cursor.execute("select * from equity")
rows = self.cursor.fetchall()
print(
"{:^10}\t{:^8}\t{:^10}\t{:^20}\t{:^10}\t{:^10}\t{:^10}\t{:^10}\t{:^10}\t{:^10}\t{:^10}\t{:^10}\t{:^10}\t".format(
"序號", "程式碼", "名稱", "最新價(元)", "漲跌幅(%)", "跌漲額(元)", "成交量", "成交額(元)", "振幅(%)", "最高", "最低", "今開", "昨收"))
i = 1
for row in rows:
print("{:^10}\t{:^8}\t{:^10}\t{:^20}\t{:^10}\t{:^18}\t{:^16}\t{:^10}\t{:^10}\t{:^10}\t{:^10}\t{:^10}\t{:^10}\t".format(i, row[0],row[1],row[2],row[3],row[4],row[5],row[6],row[7],row[8],row[9],row[10],row[11],))
i += 1
- openDB 方法:嘗試連線 SQLite 資料庫並建立一個名為 equity 的表。如果表已經存在,則刪除其中的所有記錄;使用 try...except 塊來處理表建立的異常,這樣在表已存在的情況下不會中斷程式。
- closeDB 方法:
提交任何未儲存的更改並關閉資料庫連線。
- insert 方法:插入一條股票記錄。使用 try...except 塊捕捉可能的異常,確保程式碼的健壯性。
- show 方法:從資料庫中查詢所有記錄並列印。格式化輸出使得結果在控制檯上看起來整齊。
b、輸出資訊
c、Gitee資料夾連結
2)心得體會
- 正規表示式在資料提取方面非常有效,但過度使用可能會導致程式碼可讀性降低。可以考慮使用 JSON 解析庫(如 json 模組)直接處理 API 返回的資料,這樣可以簡化程式碼並提高可讀性。
- 資料庫表的設計較為簡單,適用於小型專案。對於大規模資料,可能需要考慮更復雜的表設計和索引策略。
作業③
1)爬取中國大學 2020主榜所有院校資訊,並儲存在資料庫中
a、主要程式碼展示和分析
該函式從獲取的JSON資料中提取前 num 名大學的資訊,並將這些資訊儲存到 ulist 列表中,同時格式化輸出這些大學的排名資訊
def printUnivList(ulist, html, num):
'''提取 html 網頁內容中 前 num 名大學資訊到 ulist列表中 '''
data = json.loads(html) # 對資料進行解碼
# 提取 資料 rankings 包含的內容
content = data['data']['rankings']
# 把 學校的相關資訊放到 ulist 裡面
for i in range(num):
index = content[i]['rankOverall']
name = content[i]['univNameCn']
score = content[i]['score']
category = content[i]['univCategory']
province = content[i]['province'] # 提取省份資訊
ulist.append([index, name, score, category, province])
# 列印前 num 名的大學
tplt = "{0:^10}\t{1:^10}\t{2:^10}\t{3:^10}\t{4:^10}" # 更新格式,而不使用{3}
print(tplt.format("排名 ", "學校名稱", "總分", "型別", "省份")) # 更新這裡,保持一致
for i in range(num):
u = ulist[i]
print(tplt.format(u[0], u[1], u[2], u[3], u[4])) # 直接傳入值
- 使用了 json.loads 對網頁的返回內容進行JSON解碼,這意味著該網頁返回的資料是一個JSON格式的結構。
- 從 data['data']['rankings'] 提取大學的具體排名資訊,包含排名、學校名稱、得分、類別(如綜合類、理工類等)以及所在省份。
- 使用 tplt 定義了表格的輸出格式,確保列印的大學資訊整齊對齊。使用了 center(^) 方式格式化輸出。
該函式 將提取到的大學資訊儲存到SQLite資料庫中
def save_to_db(ulist):
'''將大學資訊儲存到SQLite資料庫'''
conn = sqlite3.connect('school.db')
cursor = conn.cursor()
# 建立表
cursor.execute('''
CREATE TABLE IF NOT EXISTS university_rankings (
rank INTEGER,
name TEXT,
score REAL,
category TEXT,
province TEXT -- 新增省份列
)
''')
# 插入資料
cursor.executemany('''
INSERT INTO university_rankings (rank, name, score, category, province)
VALUES (?, ?, ?, ?, ?)
''', ulist)
conn.commit() # 提交事務
conn.close() # 關閉連線
- 首先使用 sqlite3.connect() 連線到本地的 school.db 資料庫檔案,如果該檔案不存在,會自動建立。
- 使用 CREATE TABLE IF NOT EXISTS 建立一個名為 university_rankings 的表,這個表包含了排名、學校名稱、得分、類別和省份資訊。
- executemany() 方法批次插入大學資訊, ? 佔位符用於防止SQL隱碼攻擊風險。
- 在插入資料後,呼叫 commit() 提交事務,然後關閉資料庫連線。
b、輸出資訊
c、瀏覽器 F12 除錯分析的過程
d、Gitee資料夾連結
2)心得體會
- 使用SQLite資料庫儲存資料是一種輕量級的選擇,適用於小型專案。這種方式無需安裝複雜的資料庫系統,適合初學者學習資料庫操作。
- 整個程式按照功能劃分為多個函式,每個函式都執行一個特定的任務:獲取網頁、提取資料、列印資料、儲存資料。這樣的設計使得程式碼易於維護和擴充套件。