第一個爬蟲程序之定向爬取中國大學排名(收穫良多,不僅僅是寫個程序,更是編程的想法)
名稱:定向爬取——中國大學排名定向爬取
首先,爬之前,看看你要定向爬取的網站和數據是什麼類型的?
- 打開你要爬取網站,看看信息是否是直接寫在html中,還是由js語言生成的?從而確定你爬取的方式
如下圖,很容易的看到,信息是直接寫在html頁面中的,直接爬取html頁面,然後將信息篩選出來就行了
- 看到你要的信息在一堆的標籤中,要找到你需要的信息在哪一個標籤中,簡單的分析一下這個標籤樹!看着有點煩,直接用response.prettify()輸出看過去更直觀,如下圖
如下圖,咱們從清華看起(誰叫它第一,雖然我的學校和清華就差了一個字,我也想拿他示範,可它墊底,不明顯)。
- 清華的數據模塊和北大的數據模塊明顯的用了一個< tr >…< /tr >的標籤相互分割
- 每一個數據模塊裏面的一些小的數據又是用< td > … < /td >標籤進行包裹
- 總結一下:我們要找的數據就是大學名稱和排名,以及所在地區。就主要識別兩種標籤< tr > … < /tr >和< td >…< /td >
然後,程序的結構設計
- 根據你知道的爬取網頁的常規步驟和輸出的要求,如下圖,獲取信息,然後將信息保存在相關的框架中,然後按照下圖的格式進行輸出。顯而易見的,就是將信息保存在對應的列表中
-
故將程序分爲三個步驟,每一步都確定一個方法名
- 從網絡上獲取大學排名網頁內容——getHTMLText()
- 提取網頁信息中的信息到合適的數據結構中——fillUnivList()
- 利用數據結構展示並輸出結果——printUnivList()
-
怎麼講那,以前編程那是胡來,上來就是幹,沒有一點邏輯性,往往最後總是不停的debug浪費了太多的時間,個人認爲應該一開始就確定好程序的結構。
接着,開始程序的編寫
- 第一步,多的不寫,統攬全局走一波
- 確定每一個方法的參數類型和返回類型
- 在main方法中將所有的方法聯繫起來
# 獲取html的方法
def getHTMLtext(url):
return ""
# 將獲取的html信息提取,並將之填寫到對應的表格中
def fillUnivList(text):
univList = list()
return univList
# 將已經填寫好的數據進行輸出,num確定你要輸出的列表的項數
def printUnivList(alist,num):
print(alist)
# main方法,將所有方法進行統攬,進而形成一個完整的程序
def main():
url = "http://www.zuihaodaxue.com/zuihaodaxuepaiming2020.html"
text = getHTMLtext(url)
uniList = fillUnivList(text)
printUnivList(uniList,40)
# 總的調用
main()
- 第二步,逐步完善每一個方法
- 完善getHTMLtext()
- 在此不做詳解,詳見之前的一篇博客
# 獲取html的方法
def getHTMLtext(url):
try:
r = requests.get(url)
# 獲取response對象
r.raise_for_status()
# 判定是否已經爬取成功
r.encoding = r.apparent_encoding
# 將對應的編碼集進行轉化
return r.text
except:
return ""
- 完善fillUnivList()
# 將獲取的html信息提取,並將之填寫到對應的表格中
def fillUnivList(text):
univList = list()
soup = BeautifulSoup(text,'html.parser')
for tr in soup.find('tbody').children:
# 找到包含所有的大學信息的tbody標籤,然後遍歷對應的兒子標籤
if isinstance(tr,bs4.element.Tag):
# 注意一定要判定一下,因爲tbody的兒子標籤中有非標籤的類型
tds = tr('td')
# 獲取tr中的所有的大學的信息
univList.append([tds[0].string,tds[1].string,tds[2].string])
# 對應的td分別是學校名,排名,分數等
# 注意一定是將對應的字符串信息傳入對應的列表中,不是標籤
return univList
- 完善printUnivList()
# 將已經填寫好的數據進行輸出
def printUnivList(alist,nums):
print("{:^10}\t{:^8}\t{:^15}".format("學校名稱","排名","所在地區"))
for i in range(nums):
print("{:^10}\t{:^13}\t{:^10}".format(alist[i][0],alist[i][1],alist[i][2]))
代碼總和
import requests
from bs4 import BeautifulSoup
import bs4
# 獲取html的方法
def getHTMLtext(url):
try:
r = requests.get(url)
r.raise_for_status()
r.encoding = r.apparent_encoding
return r.text
except:
return ""
# 將獲取的html信息提取,並將之填寫到對應的表格中
def fillUnivList(text):
univList = list()
soup = BeautifulSoup(text,'html.parser')
for tr in soup.find('tbody').children:
if isinstance(tr,bs4.element.Tag):
tds = tr('td')
univList.append([tds[0].string,tds[1].string,tds[2].string])
return univList
# 將已經填寫好的數據進行輸出
def printUnivList(alist,nums):
print("{:^10}\t{:^10}\t{:^10}".format("學校名稱","排名","總和評分"))
for i in range(nums):
print("{:^10}\t{:^10}\t{:^10}".format(alist[i][0],alist[i][1],alist[i][2]))
print(alist)
# main方法,將所有方法進行統攬,進而形成一個完整的程序
def main():
url = "http://www.zuihaodaxue.com/zuihaodaxuepaiming2020.html"
text = getHTMLtext(url)
uniList = fillUnivList(text)
printUnivList(uniList,40)
# 總的調用
main()
運行結果
代碼的改良和優化——主要是針對輸出排版的優化和改良
- format函數的內容,其中填充默認採用的是英文的空格,如果輸出漢字,不能夠很好的對齊。中文空格和英文空格的寬度不同,不能夠很好的居中
- 解決辦法:專門說明填充字符的選擇——採用chr(12288)指定的中文字符空格填充
- 代碼
def printUnivList(alist,nums):
tplt = "{0:^10}\t{1:{3}^10}\t{2:^10}"
print(tplt.format("學校名稱","排名","所在地區",chr(12288)))
for i in range(nums):
print(tplt.format(alist[i][0],alist[i][1],alist[i][2],chr(12288)))
print(alist)
- 雖然個人覺得不是很重要,但是好歹是一個知識點可以積累一下
總結
- 確實搭建好了對應的框架,確定好了程序的各個參數,編程的效率確實高了很多,根據一部分來寫全部
- 總體來看,程序的美觀程度確實高了很多,應當在方法和分析上多加練習