Python爬蟲庫-Beautiful Soup的使用

2021-02-13 Python開發

擊上方「Python開發」,選擇「置頂公眾號」

關鍵時刻,第一時間送達!

Beautiful Soup是一個可以從HTML或XML文件中提取數據的Python庫,簡單來說,它能將HTML的標籤文件解析成樹形結構,然後方便地獲取到指定標籤的對應屬性。

通過Beautiful Soup庫,我們可以將指定的class或id值作為參數,來直接獲取到對應標籤的相關數據,這樣的處理方式簡潔明了。

當前最新的 Beautiful Soup 版本為4.4.0,Beautiful Soup 3 當前已停止維護。

Beautiful Soup 4 可用於 Python2.7 和 Python3.0,本文示例使用的Python版本為2.7。

博主使用的是Mac系統,直接通過命令安裝庫:

sudo easy_install beautifulsoup4

安裝完成後,嘗試包含庫運行:

from bs4 import BeautifulSoup

若沒有報錯,則說明庫已正常安裝完成。

開始

本文會通過這個網頁http://reeoo.com來進行示例講解,如下圖所示

BeautifulSoup 對象初始化

將一段文檔傳入 BeautifulSoup 的構造方法,就能得到一個文檔對象。如下代碼所示,文檔通過請求url獲取:


from bs4 import BeautifulSoup
import urllib2
url = 'http://reeoo.com'
request = urllib2.Request(url)
response = urllib2.urlopen(request, timeout=20)
content = response.read()
soup = BeautifulSoup(content, 'html.parser')

request 請求沒有做異常處理,這裡暫時先忽略。BeautifulSoup 構造方法的第二個參數為文檔解析器,若不傳入該參數,BeautifulSoup會自行選擇最合適的解析器來解析文檔,不過會有警告提示。

也可以通過文件句柄來初始化,可先將HTML的源碼保存到本地同級目錄 reo.html,然後將文件名作為參數:

soup = BeautifulSoup(open('reo.html'))

可以列印 soup,輸出內容和HTML文本無二致,此時它為一個複雜的樹形結構,每個節點都是Python對象。

Ps. 接下來示例代碼中所用到的 soup 都為該soup。

Tag

Tag對象與HTML原生文檔中的標籤相同,可以直接通過對應名字獲取

tag = soup.title
print tag

列印結果:

<title>Reeoo - web design inspiration and website gallery</title>

Name

通過Tag對象的name屬性,可以獲取到標籤的名稱

print tag.name

Attributes

一個tag可能包含很多屬性,如id、class等,操作tag屬性的方式與字典相同。

例如網頁中包含縮略圖區域的標籤 article

...
<article class="box">
   <div id="main">
   <ul id="list">
       <li id="sponsor"><div class="sponsor_tips"></div>
           <script async type="text/javascript" src="//cdn.carbonads.com/carbon.js?zoneid=1696&serve=CVYD42T&placement=reeoocom" id="_carbonads_js"></script>
       </li>
...

獲取它 class 屬性的值

tag = soup.article
c = tag['class']
print c    

也可以直接通過 .attrs 獲取所有的屬性

tag = soup.article
attrs = tag.attrs
print attrs

ps. 因為class屬於多值屬性,所以它的值為數組。

tag中的字符串

通過 string 方法獲取標籤中包含的字符串

tag = soup.title
s = tag.string
print s

文檔樹的遍歷

一個Tag可能包含多個字符串或其它的Tag,這些都是這個Tag的子節點。Beautiful Soup提供了許多操作和遍歷子節點的屬性。

子節點

通過Tag的 name 可以獲取到對應標籤,多次調用這個方法,可以獲取到子節點中對應的標籤。

如下圖:

我們希望獲取到 article 標籤中的 li

tag = soup.article.div.ul.li
print tag

列印結果:

<li id="sponsor"><div class="sponsor_tips"></div>
<script async="" id="_carbonads_js" src="//cdn.carbonads.com/carbon.js?zoneid=1696&serve=CVYD42T&placement=reeoocom" type="text/javascript"></script>
</li>

也可以把中間的一些節點省略,結果也一致

tag = soup.article.li

通過 . 屬性只能獲取到第一個tag,若想獲取到所有的 li 標籤,可以通過 find_all() 方法

ls = soup.article.div.ul.find_all('li')

獲取到的是包含所有li標籤的列表。

tag的 .contents 屬性可以將tag的子節點以列表的方式輸出:

tag = soup.article.div.ul
contents = tag.contents

列印 contents 可以看到列表中不僅包含了 li 標籤內容,還包括了換行符 ' '
過tag的 .children 生成器,可以對tag的子節點進行循環

tag = soup.article.div.ul
children = tag.children
print children
for child in children:
   print child

可以看到 children 的類型為 
.contents 和 .children 屬性僅包含tag的直接子節點,若要遍歷子節點的子節點,可以通過 .descendants 屬性,方法與前兩者類似,這裡不列出來了。

父節點

通過 .parent 屬性來獲取某個元素的父節點,article 的 父節點為 body。

tag = soup.article
print tag.parent.name

或者通過 .parents 屬性遍歷所有的父輩節點。

tag = soup.article
for p in tag.parents:
   print p.name

兄弟節點

.next_sibling 和 .previous_sibling 屬性用來插敘兄弟節點,使用方式與其他的節點類似。

文檔樹的搜索

對樹形結構的文檔進行特定的搜索是爬蟲抓取過程中最常用的操作。

find_all()

find_all(name , attrs , recursive , string , ** kwargs)

name 參數

查找所有名字為 name 的tag

soup.find_all('title')
# [<title>Reeoo - web design inspiration and website gallery</title>]
soup.find_all('footer')
# [<footer id="footer"><div class="box"><p> ... </div></footer>]

keyword 參數

如果指定參數的名字不是內置的參數名(name , attrs , recursive , string),則將該參數當成tag的屬性進行搜索,不指定tag的話則默認為對所有tag進行搜索。

如,搜索所有 id 值為 footer 的標籤

soup.find_all(id='footer')
# [<footer id="footer"><div class="box"><p> ... </div></footer>]

加上標籤的參數

soup.find_all('footer', id='footer')
# [<footer id="footer"><div class="box">n<p> ... </div>n</footer>]
# 沒有id值為'footer'的div標籤,所以結果返回為空
soup.find_all('div', id='footer')
# []

獲取所有縮略圖的 div 標籤,縮略圖用 class 為 thumb 標記

soup.find_all('div', class_='thumb')

這裡需要注意一點,因為 class 為Python的保留關鍵字,所以作為參數時加上了下劃線,為「class_」。

指定名字的屬性參數值可以包括:字符串、正則表達式、列表、True/False。

True/False

是否存在指定的屬性。

搜索所有帶有 target 屬性的標籤

soup.find_all(target=True)

搜索所有不帶 target 屬性的標籤(仔細觀察會發現,搜索結果還是會有帶 target 的標籤,那是不帶 target 標籤的子標籤,這裡需要注意一下。)

soup.find_all(target=False)

可以指定多個參數作為過濾條件,例如頁面縮略圖部分的標籤如下所示:

...
<li>
   <div class="thumb">
       <a href="http://reeoo.com/aim-creative-studios">![AIM Creative Studios](http://upload-images.jianshu.io/upload_images/1346917-f6281ffe1a8f0b18.gif?imageMogr2/auto-orient/strip)</a>
   </div>
   <div class="title">
       <a href="http://reeoo.com/aim-creative-studios">AIM Creative Studios</a>
   </div>
</li>
...

搜索 src 屬性中包含 reeoo 字符串,並且 class 為 lazy 的標籤:

soup.find_all(src=re.compile("reeoo.com"), class_='lazy')

搜索結果即為所有的縮略圖 img 標籤。

有些屬性不能作為參數使用,如 data-**** 屬性。在上面的例子中,data-original 不能作為參數使用,運行起來會報錯,SyntaxError: keyword can't be an expression*。

attrs 參數

定義一個字典參數來搜索對應屬性的tag,一定程度上能解決上面提到的不能將某些屬性作為參數的問題。

例如,搜索包含 data-original 屬性的標籤

print soup.find_all(attrs={'data-original': True})

搜索 data-original 屬性中包含 reeoo.com 字符串的標籤

soup.find_all(attrs={'data-original': re.compile("reeoo.com")})

搜索 data-original 屬性為指定值的標籤

soup.find_all(attrs={'data-original': 'http://media.reeoo.com/Bersi Serlini Franciacorta.png!page'})

string 參數

和 name 參數類似,針對文檔中的字符串內容。

搜索包含 Reeoo 字符串的標籤:

soup.find_all(string=re.compile("Reeoo"))

列印搜索結果可看到包含3個元素,分別是對應標籤裡的內容,具體見下圖所示

limit 參數

find_all() 返回的是整個文檔的搜索結果,如果文檔內容較多則搜索過程耗時過長,加上 limit 限制,當結果到達 limit 值時停止搜索並返回結果。

搜索 class 為 thumb 的 div 標籤,只搜索3個

soup.find_all('div', class_='thumb', limit=3)

列印結果為一個包含3個元素的列表,實際滿足結果的標籤在文檔裡不止3個。

recursive 參數

find_all() 會檢索當前tag的所有子孫節點,如果只想搜索tag的直接子節點,可以使用參數 recursive=False。

find()

find(name , attrs , recursive , string , ** kwargs)

find() 方法和 find_all() 方法的參數使用基本一致,只是 find() 的搜索方法只會返回第一個滿足要求的結果,等價於 find_all() 方法並將limit設置為1。

soup.find_all('div', class_='thumb', limit=1)
soup.find('div', class_='thumb')

搜索結果一致,唯一的區別是 find_all() 返回的是一個數組,find() 返回的是一個元素。

當沒有搜索到滿足條件的標籤時,find() 返回 None, 而 find_all() 返回一個空的列表。

CSS選擇器

Tag 或 BeautifulSoup 對象通過 select() 方法中傳入字符串參數, 即可使用CSS選擇器的語法找到tag。

語義和CSS一致,搜索 article 標籤下的 ul 標籤中的 li 標籤

print soup.select('article ul li')

通過類名查找,兩行代碼的結果一致,搜索 class 為 thumb 的標籤

soup.select('.thumb')
soup.select('[class~=thumb]')

通過id查找,搜索 id 為 sponsor 的標籤

soup.select('#sponsor')

通過是否存在某個屬性來查找,搜索具有 id 屬性的 li 標籤

soup.select('li[id]')

通過屬性的值來查找查找,搜索 id 為 sponsor 的 li 標籤

soup.select('li[id="sponsor"]')

其他

其他的搜索方法還有:

find_parents() 和 find_parent()

find_next_siblings() 和 find_next_sibling()

find_previous_siblings() 和 find_previous_sibling()

參數的作用和 find_all()、find() 差別不大,這裡就不再列舉使用方式了。這兩個方法基本已經能滿足絕大部分的查詢需求。

還有一些方法涉及文檔樹的修改。對於爬蟲來說大部分工作只是檢索頁面的信息,很少需要對頁面源碼做改動,所以這部分的內容也不再列舉。

【點擊成為Java大神】

相關焦點

  • Python爬蟲系列:BeautifulSoup庫詳解
    至於為什麼後面有個4(代表版本號),因為BeautifulSoup3項目已停止開發,BeautifulSoup4也已被納入到bs4裡面了,所以在引用該庫時需要使用:from bs4 import BeautifulSoup
  • Python筆記 | 使⽤ Beautiful Soup 解析數據
    Beautiful Soup的簡介簡單來說,Beautiful Soup是python的⼀個庫,最主要的功能是從⽹⻚抓取數據。官⽅解釋如下:Beautiful Soup提供⼀些簡單的、python式的函數⽤來處理導航、搜索、修改分析樹等功能。
  • Python 爬蟲基礎教程——BeautifulSoup抓取入門
    vscode開發環境的時候會遇到的問題以及使用正則表達式的方式爬取頁面信息,本篇內容主要是介紹BeautifulSoup模塊的使用教程。簡單來說Beautiful Soup是python的一個庫,是一個可以從網頁抓取數據的利器。
  • python爬蟲之BeautifulSoup
    Beautiful Soup已成為和lxml、html6lib一樣出色的python解釋器,為用戶靈活地提供不同的解析策略或強勁的速度。還可以直接使用print soup.p['class']get方法用於得到標籤下的屬性值,注意這是一個重要的方法,在許多場合都能用到,比如你要得到標籤下的圖像url,那麼就可以用soup.img.get('src'),具體解析如下:print soup.p.get("class") #得到第一個p標籤下的src屬性得到標籤下的文本內容,只有在此標籤下沒有子標籤
  • BeautifulSoup 詳細知識(一)
    beautifulsoup4Beautiful Soup提供一些簡單的、python
  • Python 爬蟲實戰(一):使用 requests 和 BeautifulSoup
    key1=value1&key2=value2 ,Requests 允許你使用 params 關鍵字參數,以一個字符串字典來提供這些參數。BeautifulSoup 3 目前已經停止開發,直接使用BeautifulSoup 4。Mac:pip3 install beautifulsoup4Windows:pip install beautifulsoup4我用的是 html5lib,純 Python 實現的。
  • Python: BeautifulSoup庫入門
    本文對BeautifulSoup模塊的使用進行簡單的介紹。  This is a python demo page  </title> </head> <body>  <p class="title">   <b>   The demo python introduces several python courses.
  • python爬蟲常用庫之BeautifulSoup詳解
    因為是第三方庫所以我們需要下載,在命令行敲下以下代碼進行下載pip install beautifulsoup4安裝第三方解析庫如果不知道有什麼用請往下看1.相關解析庫的介紹這裡官方推薦解析庫為lxml,因為它的效率高。
  • 11-python爬蟲之Beautiful Soup
    Selenium官網的Document裡極力推薦使用CSS locator,而不是XPath來定位元素,原因是CSS locator比XPath locator速度快.Beautiful SoupBeautiful Soup自動將輸入文檔轉換為Unicode編碼,輸出文檔轉換為utf-8編碼。
  • 我用Beautifulsoup(1)
    第5步:在輸入框,輸入beautifulsoup第6步:點擊搜索出的beautifulsoup4安裝完成後會顯示:Package'beautifulsoup4' installed successfully
  • HTML解析之BeautifulSoup
    官方文檔:https://beautifulsoup.readthedocs.io/zh_CN/latest/pip 安裝:pip install bs4或者pip install beautifulsoup4BeautifulSoup使用語法:
  • Python3中BeautifulSoup的使用方法
    BeautifulSoup已成為和lxml、html6lib一樣出色的python解釋器,為用戶靈活地提供不同的解析策略或強勁的速度。所以說,利用它我們可以省去很多繁瑣的提取工作,提高解析效率。安裝使用之前,我們當然需要首先說明一下它的安裝方式。
  • Python 爬蟲之 BeautifulSoup
    爬蟲之BeautifulSoup/如有好文章投稿,請點擊 → 這裡了解詳情簡介Beautiful Soup提供一些簡單的、python式的函數用來處理導航、搜索、修改分析樹等功能。Beautiful Soup已成為和lxml、html6lib一樣出色的python解釋器,為用戶靈活地提供不同的解析策略或強勁的速度。
  • 如何使用 Python 和 BeautifulSoup 爬取網站
    我們將使用 Python 作為爬取語言,並使用一個簡單而強大的庫 BeautifulSoup。接下來,我們需要使用 pip(一個 Python 包管理工具)獲取 BeautifulSoup 庫。# 取得 class 為 name 的 <div> 並獲取它的值name_box = soup.find(『h1』, attrs={『class』: 『name』})現在,我們有一個包含頁面 HTML 的變量 soup。從這裡開始我們可以編寫提取數據的代碼了。還記得我們需要的數據所獨有的標籤層次嗎?
  • BeautifulSoup 十分鐘快速上手指南
    $ pip install beautifulsoup4$ pip install lxml開始使用>>> from bs4 import BeautifulSoup>>> soup = BeautifulSoup("<html>data</html>", "html.parser")
  • 使用requests+BeautifulSoup的簡單爬蟲練習
    什麼都不管,立即來個get請求import requestsfrom bs4 import BeautifulSoupurl_start = 'http://maoyan.com/board/4'response = requests.get(url_start)if response.status_code == 200:    soup
  • Python爬蟲從入門到精通(3): BeautifulSoup用法總結及多線程爬蟲爬取糗事百科
    安裝和使用只需要使用如下兩個命令:pip install beautifulsoup4from bs4 import BeautifulSoup我們還建議你安裝lxml HTML解析庫,比python自帶的解析庫html.parser更快。
  • BeautifulSoup | 讓你一次性搞清楚BeautifulSoup!(上)
    說到BeautifulSoup大家一定都不陌生,它是python的一個庫,最主要的功能是從網頁抓取數據,但是繁瑣的規矩和看不懂網頁的結構總讓人似懂非懂
  • 爬蟲入門系列(四):HTML文本解析庫BeautifulSoup
    安裝 BeautifulSouppip install beautifulsoup4BeautifulSoup3 被官方放棄維護,你要下載最新的版本 BeautifulSoup4。HTML 標籤學習 BeautifulSoup4 前有必要先對 HTML 文檔有一個基本認識,如下代碼,HTML 是一個樹形組織結構。
  • Python爬蟲教學(寫給入門的新手)
    前言剛學完python基礎,想學習爬蟲的新手,這裡有你想要的東西。