python3解析庫BeautifulSoup4的安裝配置與基本用法
前言
Beautiful Soup是python的一個HTML或XML的解析庫,我們可以用它來方便的從網(wǎng)頁中提取數(shù)據(jù),它擁有強大的API和多樣的解析方式。
Beautiful Soup的三個特點:
- Beautiful Soup提供一些簡單的方法和python式函數(shù),用于瀏覽,搜索和修改解析樹,它是一個工具箱,通過解析文檔為用戶提供需要抓取的數(shù)據(jù)
- Beautiful Soup自動將轉(zhuǎn)入穩(wěn)定轉(zhuǎn)換為Unicode編碼,輸出文檔轉(zhuǎn)換為UTF-8編碼,不需要考慮編碼,除非文檔沒有指定編碼方式,這時只需要指定原始編碼即可
- Beautiful Soup位于流行的Python解析器(如lxml和html5lib)之上,允許您嘗試不同的解析策略或交易速度以獲得靈活性。
1、Beautiful Soup4的安裝配置
Beautiful Soup4通過PyPi發(fā)布,所以可以通過系統(tǒng)管理包工具安裝,包名字為beautifulsoup4
$easy_install beautifulsoup4
或者
$pip install beautifulsoup4
也可用通過下載源碼包來安裝:
#wget https://www.crummy.com/software/BeautifulSoup/bs4/download/4.0/beautifulsoup4-4.1.0.tar.gz #tar xf beautifulsoup4-4.1.0.tar.gz #cd beautifulsoup4 #python setup.py install
Beautiful Soup在解析時實際上是依賴解析器的,它除了支持python標準庫中的HTML解析器外還支持第三方解析器如lxml
Beautiful Soup支持的解析器,以及它們的優(yōu)缺點:
解析器 | 使用方法 | 優(yōu)勢 | 劣勢 |
---|---|---|---|
Python標準庫 | BeautifulSoup(markup,"html.parser") |
|
|
lxml HTML 解析器 | BeautifulSoup(markup,"lxml") |
|
|
lxml XML 解析器 |
BeautifulSoup(markup,["lxml", "xml"]) BeautifulSoup(markup,"xml") |
|
|
html5lib | BeautifulSoup(markup,"html5lib") |
|
|
安裝解析器:
$pip install lxml $pip install html5lib
推薦使用lxml作為解析器,因為效率更高. 在Python2.7.3之前的版本和Python3中3.2.2之前的版本,必須安裝lxml或html5lib, 因為那些Python版本的標準庫中內(nèi)置的HTML解析方法不夠穩(wěn)定
2、BeautifulSoup的基本用法
通過傳入一段字符或一個文件句柄,BeautifulSoup的構(gòu)造方法就能得到一個文檔的對象,選擇合適的解析器來解析文檔,如手動指定將選擇指定的解析器來解析文檔,Beautiful Soup將復雜的HTML文檔轉(zhuǎn)換成一個復雜的樹形結(jié)構(gòu),每個節(jié)點都是python對象,所有對象可以歸納為4種:Tag、NavigableString、BeautifulSoup、Comment
注意:BeautifulSoup版本4的包是在bs4中引入的
from bs4 import BeautifulSoup #下面代碼示例都是用此文檔測試 html_doc = """ <html><head><title>The Dormouse's story</title></head> <body> <p class="title"><b>The Dormouse's story</b></p> <p class="story">Once upon a time there were three little sisters; and their names were <a rel="external nofollow" class="sister" id="link1">Elsie</a>, <a rel="external nofollow" class="sister" id="link2">Lacie</a> and <a rel="external nofollow" class="sister" id="link3">Tillie</a>; and they lived at the bottom of a well.</p> <p class="story">...</p> """ markup="<b><!--Hey, buddy. Want to buy a used parser?--></b>" soup=BeautifulSoup(html_doc,"lxml") soup1=BeautifulSoup(markup,"lxml") tag=soup.a navstr=tag.string comment=soup1.b.string print(type(tag)) #Tag標簽對象 print(type(comment)) #Comment對象包含文檔注釋內(nèi)容 print(type(navstr)) #NavigableString對象包裝字符串內(nèi)容 print(type(soup)) #BeautifulSoup對象為文檔的全部內(nèi)容 # <class 'bs4.element.Tag'> <class 'bs4.element.Comment'> <class 'bs4.element.NavigableString'> <class 'bs4.BeautifulSoup'>
(1)節(jié)點選擇器(tag)
直接調(diào)用節(jié)點的名稱就可以選擇節(jié)點元素,節(jié)點可以嵌套選擇返回的類型都是bs4.element.Tag對象
soup=BeautifulSoup(html_doc,'lxml') print(soup.head) #獲取head標簽 print(soup.p.b) #獲取p節(jié)點下的b節(jié)點 print(soup.a.string) #獲取a標簽下的文本,只獲取第一個
name屬性獲取節(jié)點名稱:
soup.body.name
attrs屬性獲取節(jié)點屬性,也可以字典的形式直接獲取,返回的結(jié)果可能是列表或字符串類型,取決于節(jié)點類型
soup.p.attrs #獲取p節(jié)點所有屬性 soup.p.attrs['class'] #獲取p節(jié)點class屬性 soup.p['class'] #直接獲取p節(jié)點class屬性
string屬性獲取節(jié)點元素包含的文本內(nèi)容:
soup.p.string #獲取第一個p節(jié)點下的文本內(nèi)容
contents屬性獲取節(jié)點的直接子節(jié)點,以列表的形式返回內(nèi)容
soup.body.contents #是直接子節(jié)點,不包括子孫節(jié)點
children屬性獲取的也是節(jié)點的直接子節(jié)點,只是以生成器的類型返回
soup.body.children
descendants屬性獲取子孫節(jié)點,返回生成器
soup.body.descendants
parent屬性獲取父節(jié)點,parents獲取祖先節(jié)點,返回生成器
soup.b.parent soup.b.parents
next_sibling屬性返回下一個兄弟節(jié)點,previous_sibling返回上一個兄弟節(jié)點,注意換行符也是一個節(jié)點,所以有時候在獲取兄弟節(jié)點是通常是字符串或者空白
soup.a.next_sibling soup.a.previous_sibling
next_siblings和previous_sibling分別返回前面和后面的所有兄弟節(jié)點,返回生成器
soup.a.next_siblings soup.a.previous_siblings
next_element和previous_element屬性獲取下一個被解析的對象,或者上一個
soup.a.next_element soup.a.previous_element
next_elements和previous_elements迭代器向前或者后訪問文檔解析內(nèi)容
soup.a.next_elements soup.a.previous_elements
(2)方法選擇器
前面使用的都是通過節(jié)點屬性來選擇的,這種方法非???,但在進行比較復雜的選擇時就不夠靈活,幸好Beautiful Soup還為我們提供了一些查詢方法,如fang_all()和find()等
find_all(name,attrs,recursive,text,**kwargs):查詢所有符合條件的元素,其中的參數(shù)
name表示可以查找所有名字為name的標簽(tag),也可以是過濾器,正則表達式,列表或者是True
attrs表示傳入的屬性,可以通過attrs參數(shù)以字典的形式指定如常用屬性id,attrs={'id':'123'},由于class屬性是python中的關(guān)鍵字,所有在查詢時需要在class后面加上下劃線即class_='element',返回的結(jié)果是tag類型的列表
text參數(shù)用來匹配節(jié)點的文本,傳入的形式可以是字符串也可以是正則表達式對象
recursive表示,如果只想搜索直接子節(jié)點可以將參數(shù)設為false:recursive=Flase
limit參數(shù),可以用來限制返回結(jié)果的數(shù)量,與SQL中的limit關(guān)鍵字類似
import re from bs4 import BeautifulSoup html_doc = """ #下面示例都是用此文本內(nèi)容測試 <html><head><title>The Dormouse's story</title></head> <body> <p class="title"><b>The Dormouse's story</b></p> <p class="story">Once upon a time there were three little sisters; and their names were <a class="sister" id="link1">Elsie</a> ddd <a class="sister" id="link2">Lacie</a> and <a class="sister" id="link3">Tillie</a>; and they lived at the bottom of a well.</p> <p class="story">...</p> <span>中文</span> """ soup=BeautifulSoup(html_doc,'lxml') print(type(soup)) print(soup.find_all('span')) #標簽查找 print(soup.find_all('a',id='link1')) #屬性加標簽過濾 print(soup.find_all('a',attrs={'class':'sister','id':'link3'})) #多屬性 print(soup.find_all('p',class_='title')) #class特殊性,此次傳入的參數(shù)是**kwargs print(soup.find_all(text=re.compile('Tillie'))) #文本過濾 print(soup.find_all('a',limit=2)) #限制輸出數(shù)量 # <class 'bs4.BeautifulSoup'> [<span>中文</span>] [<a class="sister" id="link1">Elsie</a>] [<a class="sister" id="link3">Tillie</a>] [<p class="title"><b>The Dormouse's story</b></p>] ['Tillie'] [<a class="sister" id="link1">Elsie</a>, <a class="sister" id="link2">Lacie</a>]
find( name , attrs , recursive , text , **kwargs ):它返回的是單個元素,也就是第一個匹配的元素,類型依然是tag類型
參數(shù)同find_all()一樣
另外還有許多查詢方法,其用法和前面介紹的find_all()方法完全相同,只不過查詢范圍不同,參數(shù)也一樣
find_parents(name , attrs , recursive , text , **kwargs )
和find_parent(name , attrs , recursive , text , **kwargs )
:前者返回所有祖先節(jié)點,后者返回直接父節(jié)點
find_next_siblings(name , attrs , recursive , text , **kwargs )
和find_next_sibling(name , attrs , recursive , text , **kwargs )
:對當前tag后面的節(jié)點進行迭代,前者返回后面的所有兄弟節(jié)點,后者返回后面第一個兄弟節(jié)點
find_previous_siblings(name , attrs , recursive , text , **kwargs )
和find_previous_sibling(name , attrs , recursive , text , **kwargs )
:對當前tag前面的節(jié)點進行迭代,前者返回前面的所有兄弟節(jié)點,后者返回前面的第一個兄弟節(jié)點
find_all_next(name , attrs , recursive , text , **kwargs )
和find_next(name , attrs , recursive , text , **kwargs )
:對當前tag之后的tag和字符串進行迭代,前者返回所有符合條件的節(jié)點,后者返回第一個符合條件的節(jié)點
find_all_previous()
和find_previous()
:對當前tag之前的tag和字符串進行迭代,前者返回節(jié)點后所有符合條件的節(jié)點,后者返回第一個符合條件的節(jié)點
(3)CSS選擇器
Beautiful Soup還提供了CSS選擇器,如果多CSS選擇器不熟悉可以參考下http://www.w3school.com.cn/cssref/css_selectors.asp
在 Tag 或 BeautifulSoup 對象的 .select()方法中傳入字符串參數(shù),即可使用CSS選擇器的語法找到tag:
In [10]: soup.select('title') Out[10]: [<title>The Dormouse's story</title>]
通過tag標簽逐層查找:
In [12]: soup.select('body a') Out[12]: [<a class="sister" id="link1">Elsie</a>, <a class="sister" id="link2">Lacie</a>, <a class="sister" id="link3">Tillie</a>]
查找某個tag標簽下的直接子標簽:
In [13]: soup.select('head > title') Out[13]: [<title>The Dormouse's story</title>]
查找兄弟節(jié)點標簽:
In [14]: soup.select('#link1 ~ .sister') Out[14]: [<a class="sister" id="link2">Lacie</a>, <a class="sister" id="link3">Tillie</a>]
通過CSS類名查找:
In [15]: soup.select('.title') Out[15]: [<p class="title"><b>The Dormouse's story</b></p>] In [16]: soup.select('[class~=title]') Out[16]: [<p class="title"><b>The Dormouse's story</b></p>]
通過tag的id查找:
In [17]: soup.select('#link1') Out[17]: [<a class="sister" id="link1">Elsie</a>] In [18]: soup.select('a#link2') Out[18]: [<a class="sister" id="link2">Lacie</a>]
通過是否存在某個屬性來查找:
In [20]: soup.select('a[href]') Out[20]: [<a class="sister" id="link1">Elsie</a>, <a class="sister" id="link2">Lacie</a>, <a class="sister" id="link3">Tillie</a>]
通過屬性的值來查找匹配:
In [22]: soup.select('a[) Out[22]: [<a class="sister" id="link1">Elsie</a>] In [23]: soup.select('a[href^="http://example.com/"]') #匹配值的開頭 Out[23]: [<a class="sister" id="link1">Elsie</a>, <a class="sister" id="link2">Lacie</a>, <a class="sister" id="link3">Tillie</a>] In [24]: soup.select('a[href$="tillie"]') #匹配值的結(jié)尾 Out[24]: [<a class="sister" id="link3">Tillie</a>] In [25]: soup.select('a[href*=".com/el"]') #模糊匹配 Out[25]: [<a class="sister" id="link1">Elsie</a>]
tag節(jié)點查找,方法選擇器查找和CSS選擇器查找三種方法的實現(xiàn)方式基本相似,tag相對于其他兩種所有最快速的查找方式,但方法選擇器提供更便利更復雜的查找方式,使用更如有上手。
(4)tag修改方法
Beautiful Soup的強項是文檔的搜索功能,修改功能使用場景不是很多只做簡單介紹,要了解更多修改方法請前往Beautiful Soup官方文檔查看。
Beautiful Soup可以實現(xiàn)改變tag標志的屬性的值,添加或刪除屬性和內(nèi)容,下面介紹一些常用的方法
In [26]: markup='<a In [28]: soup=BeautifulSoup(markup,'lxml') In [29]: soup.a.string='百度' In [30]: soup.a Out[30]: <a >百度</a> #如果a節(jié)點下包括子也將被覆蓋掉
Tag.append() 方法想tag中添加內(nèi)容,就好像Python的列表的 .append() 方法:
In [30]: soup.a Out[30]: <a >百度</a> In [31]: soup.a.append('一下') In [32]: soup.a Out[32]: <a >百度一下</a>
new_tag()方法用于創(chuàng)建一個tag標簽
In [33]: soup=BeautifulSoup('<b></b>','lxml') In [34]: new_tag=soup.new_tag('a',) #創(chuàng)建tag,第一個參數(shù)必須為tag的名稱 In [35]: soup.b.append(new_tag) #添加到b節(jié)點下 In [36]: new_tag.string='python' #為tag設置值 In [37]: soup.b Out[37]: <b><a >python</a></b>
其他方法:
insert()將元素插入到指定的位置
inert_before()在當前tag或文本節(jié)點前插入內(nèi)容
insert_after()在當前tag或文本節(jié)點后插入內(nèi)容
clear()移除當前tag的內(nèi)容
extract()將當前tag移除文檔數(shù),并作為方法結(jié)果返回
prettify()將Beautiful Soup的文檔數(shù)格式化后以Unicode編碼輸出,tag節(jié)點也可以調(diào)用
get_text()輸出tag中包含的文本內(nèi)容,包括子孫tag中的內(nèi)容
soup.original_encoding 屬性記錄了自動識別的編碼結(jié)果
from_encoding:參數(shù)在創(chuàng)建BeautifulSoup對象是可以用來指定編碼,減少猜測編碼的運行速度
#解析部分文檔,可以使用SoupStrainer類來創(chuàng)建一個內(nèi)容過濾器,它接受同搜索方法相同的參數(shù)
from bs4 import BeautifulSoup,SoupStrainer html_doc = """ <html><head><title>The Dormouse's story</title></head> <body> <p class="title"><b>The Dormouse's story</b></p> <p class="story">Once upon a time there were three little sisters; and their names were <a class="sister" id="link1">Elsie</a> ddd <a class="sister" id="link2">Lacie</a> and <a class="sister" id="link3">Tillie</a>; and they lived at the bottom of a well.</p> <p class="story">...</p> <span>中文</span> """ only_a_tags = SoupStrainer('a') #顧慮器 soup=BeautifulSoup(html_doc,'lxml',parse_only=only_a_tags) print(soup.prettify()) # <a class="sister" id="link1"> Elsie </a> <a class="sister" id="link2"> Lacie </a> <a class="sister" id="link3"> Tillie </a>
#Beautiful Soup異常處理:
HTMLParser.HTMLParseError:malformed start tag
HTMLParser.HTMLParseError:bad end tag 這個兩個異常都是解析器引起的,解決方法是安裝lxml或者html5lib
更多內(nèi)容...
官方文檔:https://www.crummy.com/software/BeautifulSoup/bs4/doc/
中文文檔:https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh
PyPI:https://pypi.org/project/beautifulsoup4/
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關(guān)文章
Python爬蟲框架scrapy實現(xiàn)的文件下載功能示例
這篇文章主要介紹了Python爬蟲框架scrapy實現(xiàn)的文件下載功能,結(jié)合實例形式分析了scrapy框架進行文件下載的具體操作步驟與相關(guān)實現(xiàn)技巧,需要的朋友可以參考下2018-08-08python用selenium打開瀏覽器后秒關(guān)閉瀏覽器的解決辦法
最近朋友在學Selenium的時候遇到一個問題,當執(zhí)行完selenium程序后,瀏覽器會閃退也就是自動關(guān)閉,這篇文章主要給大家介紹了關(guān)于python用selenium打開瀏覽器后秒關(guān)閉瀏覽器的解決辦法,需要的朋友可以參考下2023-07-07PyTorch實現(xiàn)聯(lián)邦學習的基本算法FedAvg
這篇文章主要為大家介紹了PyTorch實現(xiàn)聯(lián)邦學習的基本算法FedAvg,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-05-05Python壓縮包處理模塊zipfile和py7zr操作代碼
目前對文件的壓縮和解壓縮比較常用的格式就是zip格式和7z格式,這篇文章主要介紹了Python壓縮包處理模塊zipfile和py7zr,需要的朋友可以參考下2022-06-06Python常用類型轉(zhuǎn)換實現(xiàn)代碼實例
這篇文章主要介紹了Python常用類型轉(zhuǎn)換實現(xiàn)代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-07-07Python 使用SFTP和FTP實現(xiàn)對服務器的文件下載功能
這篇文章主要介紹了Python 使用SFTP和FTP實現(xiàn)對服務器的文件下載功能,本文通過實例代碼給大家介紹的非常想詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-12-12