BeautifulSoup4是爬蟲必學的技能。BeautifulSoup最主要的功能是從網頁抓取數據,Beautiful Soup自動將輸入文檔轉換為Unicode編碼,輸出文檔轉換為utf-8編碼。BeautifulSoup支持Python標準庫中的HTML解析器,還支持一些第三方的解析器,如果我們不安裝它,則 Python 會使用 Python默認的解析器,lxml 解析器更加強大,速度更快,推薦使用lxml 解析器。
一、簡介
靈活又方便的網頁解析庫,處理高效,支持多種解析器。
利用它不用編寫正則表達式即可方便地實現網頁信息的提取。
安裝:pip3 install BeautifulSoup4
解析器使用方法優勢劣勢
Python標準庫BeautifulSoup(markup, “html.parser”)Python的內置標準庫、執行速度適中 、文檔容錯能力強Python 2.7.3 or 3.2.2)前的版本中文容錯能力差
lxml HTML 解析器BeautifulSoup(markup, “lxml”)速度快、文檔容錯能力強需要安裝C語言庫
lxml XML 解析器BeautifulSoup(markup, “xml”)速度快、唯一支持XML的解析器需要安裝C語言庫
html5libBeautifulSoup(markup, “html5lib”)最好的容錯性、以瀏覽器的方式解析文檔、生成HTML5格式的文檔速度慢、不依賴外部擴展
二、基本用法
#基本用法from bs4 import BeautifulSoupbs = BeautifulSoup(html,"html.parser") # 縮進格式print(bs.prettify())print(bs.prettify()) # 格式化html結構print(bs.title) # 獲取title標簽的名稱print(bs.title.name) # 獲取title的nameprint(bs.title.string) # 獲取head標簽的所有內容print(bs.head) print(bs.div) # 獲取第一個div標簽中的所有內容print(bs.div["id"]) # 獲取第一個div標簽的id的值print(bs.a) print(bs.find_all("a")) # 獲取所有的a標簽print(bs.find(id="u1")) # 獲取id="u1"for item in bs.find_all("a"): print(item.get("href")) # 獲取所有的a標簽,并遍歷打印a標簽中的href的值for item in bs.find_all("a"): print(item.get_text())#選擇元素from bs4 import BeautifulSoupsoup = BeautifulSoup(html, "lxml")print(soup.title)print(type(soup.title))print(soup.head)print(soup.p)#獲取名稱print(soup.title.name)print(soup.p.attrs["name"])print(soup.p["name"])#獲取內容print(soup.p.string)#獲取子孫節點print(soup.p.children)for i, child in enumerate(soup.p.children): print(i, child)
3.find_all( name , attrs , recursive , text , **kwargs )
可根據標簽名、屬性、內容查找文檔,返回所有符合條件的內容
#通過標簽from bs4 import BeautifulSoupsoup = BeautifulSoup(html, "lxml")print(soup.find_all("ul"))print(type(soup.find_all("ul")[0]))#通過屬性print(soup.find_all(attrs={"id": "list-1"}))print(soup.find_all(attrs={"name": "elements"}))print(soup.find_all(id="list-1"))print(soup.find_all(class_="element"))#通過textprint(soup.find_all(text="Foo"))
4.find( name , attrs , recursive , text , **kwargs )
find返回單個元素,find_all返回所有元素
from bs4 import BeautifulSoupsoup = BeautifulSoup(html, "lxml")print(soup.find("ul"))print(type(soup.find("ul")))print(soup.find("page"))
find_parents() find_parent()
find_parents()返回所有祖先節點,find_parent()返回直接父節點。
find_next_siblings() find_next_sibling()
find_next_siblings()返回后面所有兄弟節點,find_next_sibling()返回后面第一個兄弟節點。
find_previous_siblings() find_previous_sibling()
find_previous_siblings()返回前面所有兄弟節點,find_previous_sibling()返回前面第一個兄弟節點。
find_all_next() find_next()
find_all_next()返回節點后所有符合條件的節點, find_next()返回第一個符合條件的節點
find_all_previous() 和 find_previous()
find_all_previous()返回節點后所有符合條件的節點, find_previous()返回第一個符合條件的節點
5.css選擇
通過select()直接傳入CSS選擇器即可完成選擇
from bs4 import BeautifulSoupsoup = BeautifulSoup(html, "lxml")print(soup.select(".panel .panel-heading"))print(soup.select("ul li"))print(soup.select("#list-2 .element"))print(type(soup.select("ul")[0]))for ul in soup.select("ul"): print(ul.select("li"))#獲得屬性for ul in soup.select("ul"): print(ul["id"]) print(ul.attrs["id"])#獲取內容for li in soup.select("li"): print(li.get_text())三、BeautifulSoup4四大對象種類
BeautifulSoup4將復雜HTML文檔轉換成一個復雜的樹形結構,每個節點都是Python對象,所有對象可以歸納為4種:
1.Tag
我們可以利用 soup 加標簽名輕松地獲取這些標簽的內容,這些對象的類型是bs4.element.Tag。但是注意,它查找的是在所有內容中的第一個符合要求的標簽。
print(type(bs.a))
對于 Tag,它有兩個重要的屬性,是 name 和 attrs:
2.NavigableString
既然我們已經得到了標簽的內容,那么問題來了,我們要想獲取標簽內部的文字怎么辦呢?很簡單,用 .string 即可
print(type(bs.title.string))
3.BeautifulSoup
BeautifulSoup對象表示的是一個文檔的內容。大部分時候,可以把它當作 Tag 對象,是一個特殊的 Tag,我們可以分別獲取它的類型,名稱,以及屬性
4.Comment
Comment 對象是一個特殊類型的 NavigableString 對象,其輸出的內容不包括注釋符號。
四、遍歷文檔樹
1、.contents:獲取Tag的所有子節點,返回一個list
# tag的.content 屬性可以將tag的子節點以列表的方式輸出print(bs.head.contents)# 用列表索引來獲取它的某一個元素print(bs.head.contents[1])
2、.children:獲取Tag的所有子節點,返回一個生成器
for child in bs.body.children: print(child)
3.descendants:獲取Tag的所有子孫節點
4、.strings:如果Tag包含多個字符串,即在子孫節點中有內容,可以用此獲取,而后進行遍歷
5、.stripped_strings:與strings用法一致,只不過可以去除掉那些多余的空白內容
6、.parent:獲取Tag的父節點
7、.parents:遞歸得到父輩元素的所有節點,返回一個生成器
8、.previous_sibling:獲取當前Tag的上一個節點,屬性通常是字符串或空白,真實結果是當前標簽與上一個標簽之間的頓號和換行符
9、.next_sibling:獲取當前Tag的下一個節點,屬性通常是字符串或空白,真是結果是當前標簽與下一個標簽之間的頓號與換行符
10、.previous_siblings:獲取當前Tag的上面所有的兄弟節點,返回一個生成器
11、.next_siblings:獲取當前Tag的下面所有的兄弟節點,返回一個生成器
12、.previous_element:獲取解析過程中上一個被解析的對象(字符串或tag),可能與previous_sibling相同,但通常是不一樣的
13、.next_element:獲取解析過程中下一個被解析的對象(字符串或tag),可能與next_sibling相同,但通常是不一樣的
14、.previous_elements:返回一個生成器,可以向前訪問文檔的解析內容
15、.next_elements:返回一個生成器,可以向后訪問文檔的解析內容
16、.has_attr:判斷Tag是否包含屬性