Python爬蟲之Beautiful Soup庫及大學排名爬取

 

Beautiful Soup庫是解析、遍歷、維護“標籤樹”的功能庫。Beautiful Soup庫也叫beautifulsoup4 或 bs4。但主要還是用BeautifulSoup類,約定引用方式如下:

from bs4 import BeautifulSoup
import bs4

Beautiful Soup庫解析器

soup = BeautifulSoup('<html>data</html>','html.parser')

bs4的HTML解析器 BeautifulSoup(mk,'html.parser') 安裝bs4庫

lxml的HTML解析器 BeautifulSoup(mk,'lxml') pip install lxml

lxml的XML解析器 BeautifulSoup(mk,'xml') pip install lxml

html5lib解析器 BeautifulSoup(mk,'html5lib') pip install html5lib

 

BeautifulSoup類的基本元素

 

- 任何存在於HTML語法中的標籤都可以用soup.<tag>訪問獲得。當HTML文檔中存在多個相同<tag>對應內容時,soup.<tag>返回第一個。

 

- 每個<tag>都有自己的名字,通過<tag>.name獲取,字符串類型。

 

- 一個<tag>可以有0或多個屬性,字典類型.

 

- NavigableString可以跨越多個層次

 

舉例:假設我們獲得的某個網頁的文本信息如下

 

>>> from bs4 import BeautifulSoup 
>>> soup = BeautifulSoup('<html>data</html>','html.parser')
>>> soup.title  
This is d pyton demo page 
>>> soup.a.name 
'a'
>>> tag = soup.a
>>> tag.attrs
{'id':'link1','class':['py1'], 'href': 'http://....'}
>>>tag.string
'Basic Python'

 

HTML內容遍歷方法

 

下行遍歷常見屬性:

 

.contents 子節點的列表,將<tag>所有兒子節點存入列表

.children 子節點的迭代類型,與.contents類似,用於循環遍歷兒子節點

.descendants 子孫節點的迭代類型,包含所有子孫節點,用於循環遍歷

 

# 遍歷兒子節點
for child in soup.body.children:
    print(child)
# 遍歷子孫節點
for child in soup.body.descendants:
    print(child)

 

上行遍歷常見屬性:

.parent 節點的父親標籤

.parents 節點先輩標籤的迭代類型,用於循環遍歷先輩節點

 

平行遍歷常見屬性:平行遍歷發生在同一個父節點下的各節點間。

 

.next_sibling 返回按照HTML文本順序的下一個平行節點標籤

.previous_sibling 返回按照HTML文本順序的上一個平行節點標籤

.next_siblings 迭代類型,返回按照HTML文本順序的後續所有平行節點標籤

.previous_siblings 迭代類型,返回按照HTML文本順序的前續所有平行節點標籤

 

規範輸出

.prettify()方法可以使得HTML內容顯示更加規範。在每個把標籤的結尾田間一個換行符'\n' 。.prettify()可用於標籤,方法:<tag>.prettify()。​​​​​​​

print (soup.prettifu()) 
print (soup.a.prettifu())

編碼格式

bs4庫將任何HTML輸入都變成utf‐8編碼,因此我們在解析時無障礙。​​​​​​​

>>>soup = BeatifulSoup("<p>中文<\p>",'html.parser')
>>>soup.p.string
'中文' 

 

HTML信息標記方式

超文本 包括聲音、圖像、視頻。對於這類信息的標記便於我們更好的表示。標記後的信息能夠增強信息維度,更加有利於程序的理解和存儲。

 

信息標記方式可以包括三種: XML、JSON、YAML

XML       Internet上的信息交互與傳遞

JSON      移動應用雲端和節點的信息通信,無註釋

YAML     各類系統的配置文件,有註釋易讀

 

XML(eXtensible Markup Language)​​​​​​​

# XML標籤 <name> … </name>
<img src=“china.jpg” size=“10”> … </img>
# 空元素的縮寫形式 <name />
<img src=“china.jpg” size=“10” />
# 註釋書寫形式  <!‐‐ ‐‐>
<!‐‐ This is a comment, very useful ‐‐>

示例:​​​​​​​

<person>
    <firstName>公衆號</firstName>
    <lastName>花重錦城</lastName>
    <address>
        <streetAddr>重慶市北碚區</streetAddr>
        <city>重慶市</city>
        <zipcode> 033478 </zipcode>
     </address>
     <prof>Computer System</prof><prof>Security</prof>
</person>

JSON(JavsScript Object Notation)

有類型的鍵值對 key : value​​​​​​​

#有類型的鍵值對 key : value
“name” : “公衆號花重錦城”
# 其中:“”表示類型,name表示key,‘公衆號花重錦城’表示值valu  

 

當value 有多個值時用,號分隔。例如

“name” :['公衆號 ', '花重錦城']

鍵值對嵌套形式​​​​​​​

“name”: {
“FirstName” : “公衆號”,
“lastName” : “花重錦城”
}

示例:​​​​​​​

{
  “firstName” : “公衆號” ,
  “lastName” : “花重錦城” ,
  “address”  : {
              “streetAddr” : “重慶市北碚區” ,
              “city”  : “重慶市” ,
              “zipcode”  : “033478 ”
              } ,
  “prof”  : [ “Computer System” , “Security” ]
}

YAML (YAML Ain’t Markup Language)

無類型鍵值對 key:value​​​​​​​

name : “公衆號花重錦城”
# 其中:name表示key,‘公衆號花重錦城’表示值valu 
通過縮進表達所屬關係,通過 表達並列關係​​​​​​​
# 注意縮進
name :
  firstName : 公衆號
  lastName : 花重錦城
# 並列關係
name :
‐公衆號
‐花重錦城

示例:

firstName : 公衆號
lastName : 花重錦城
address  :
    streetAddr : 重慶市北碚區
    city  : 重慶市
    zipcode : 033478
prof  :
‐Computer System
‐Security

信息提取方式

信息的提取也是對網頁內容的解析,根據網頁的結構和自己需要提取內容的關鍵標識符號來進行信息的檢索,最終得到數據。在網頁的解析過程中,我們除了要明確網頁信息的表示方式之外,還要利用正則表達式定位關鍵位置實現信息提取。基於bs4庫的HTML內容查找:

>>> soup.findall('a')
>>> soup.findall(['a','b']
# 注意
<tag>(..) 等價於 <tag>.find_all(..)
soup(..)  等價於 soup.find_all(..)

 

實例,中國大學排名爬蟲

 

提示: 中文字符的空格填充 chr(12288)​​​​​​​

import requests
import bs4
from bs4 import BeautifulSoup
 
def getHTMLText(url):
    try:
        r = requests.get(url, timeout = 30)
        r.raise_for_status()
        r.encoding = r.apparent_encoding
        return r.text
    except:
        return ""
 
def fillUnivList(ulist, html):
    soup = BeautifulSoup(html, 'html.parser')
    for tr in soup.find('tbody').children:
        if isinstance(tr, bs4.element.Tag):
            tds = tr.find_all('td')
            ulist.append([tds[0].string,tds[1].string,tds[3].string])
 
def printUnivList(ulist, num):
    tplt = "{0:^10}\t{1:{3}^10}\t{2:^10}"
    print(tplt.format("排名", "學校名稱", "總分", chr(12288)))
    for i in range(num):
        u = ulist[i]
        print(tplt.format(u[0], u[1], u[2], chr(12288)))
 
def main():
    uinfo = []
    url = 'http://www.zuihaodaxue.cn/zuihaodaxuepaiming2016.html'
    html = getHTMLText(url)
    fillUnivList(uinfo, html)
    printUnivList(uinfo, 5)
 
if __name__ == "__main__":
    main()
'''out
    排名         學校名稱         總分    
    1          清華大學        95.9   
    2          北京大學        82.6   
    3          浙江大學         80 
    4           上海交通大學         78.8
    5            復旦大學            70.9
'''

 

 掃描二維碼學習瞭解更多關於python、機器學習、Linux系統以及開源軟件的知識

  

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章