爬蟲筆記之BeautifulSoup模組官方文件筆記
爬蟲筆記之BeautifulSoup模組官方文件筆記
文章開始把我喜歡的這句話送個大家:這個世界上還有什麼比自己寫的程式碼執行在一億人的電腦上更酷的事情嗎,如果有那就是讓這個數字再擴大十倍
幾個簡單的瀏覽結構化資料的方法:
soup.title
soup.title.name
soup.title.string
soup.title.parent.name//上層標籤
soup.p
soup.p[‘class’]
soup.a
soup.find_all(‘a’)//得到所有完整a標籤
for link in soup.find_all(‘a’):
print(link.get(‘href”))//得到a標籤內部的href
soup.get_text()//得到文件中所有文字的內容
Beautiful Soup支援中的解析器:
1.Python標準庫 BeautifulSoup(markup,”html.parser”)
2.lxml HTML解析器 BeautifulSoup(markup,”lxml”)
3.lxml XML 解析器 BeautifulSoup(markup,”xml”)
BeautifulSoup(markup,[“lxml-xml”])
4.html5lib BeautifulSoup(markup,”html5lib”)
推薦使用lxml作為解析器,因為效率更高
Beautiful Soup將複雜HTML文件轉換成一個複雜的樹形結構,每個節點都是Python物件,所有物件可以歸納為4種: Tag , NavigableString , BeautifulSoup , Comment .
Tag
tag的屬性操作方法與字典一樣
1.name屬性:
tag.name
2.attributes屬性:
tag.attrs//輸出字典
tag[‘class’]
3.多值屬性
在Beautiful Soup中多值屬性的返回類型是list
NavigableString
Beautiful Soup用 NavigableString 類來包裝tag中的字串
通過 unicode() 方法可以直接將 NavigableString 物件轉換成Unicode字串:
type(tag.string)//navigablestring型別
unicode_string = unicode(tag.string)
tag中包含的字串不能編輯,但是可以被替換成其它的字串,用 replace_with() 方法:
如果想在Beautiful Soup之外使用 NavigableString 物件,需要呼叫 unicode() 方法,將該物件轉換成普通的Unicode字串,否則就算Beautiful Soup已方法已經執行結束,該物件的輸出也會帶有物件的引用地址.這樣會浪費記憶體.
BeautifulSoup
物件表示的是一個文件的全部內容.大部分時候,可以把它當作 Tag 對象
Comment
表示文件的注釋部分是一個特殊類型的 NavigableString 物件:
遍歷文件樹
注意: Beautiful Soup中字串節點不支援這些屬性,因為字串沒有子節點
通過點取屬性的方式只能獲得當前名字的第一個tag
tag的 .contents 屬性可以將tag的子節點以列表的方式輸出:
支援.contents[0]形式
字串沒有 .contents 屬性,因為字串沒有子節點:
通過tag的 .children 生成器,可以對tag的子節點進行循環:
for child in title_tag.children:
print(child)
.contents 和 .children 屬性僅包含tag的直接子節點.
.descendants 屬性可以對所有tag的子孫節點進行遞迴循環
如果tag只有一個 NavigableString 型別子節點,那麼這個tag可以使用 .string 得到子節點
如果一個tag僅有一個子節點,那麼這個tag也可以使用 .string 方法,輸出結果與當前唯一子節點的 .string 結果相同:如果tag包含了多個子節點,tag就無法確定 .string 方法應該調用哪個子節點的內容, .string 的輸出結果是 None :
如果tag中包含多個字串 ,可以使用 .strings 來循環獲取:
通過 .parent 屬性來獲取某個元素的父節點.
通過元素的 .parents 屬性可以遞迴得到元素的所有父輩節點
使用 .next_sibling 和 .previous_sibling 屬性來查詢兄弟節點:
搜尋文件樹
find() 和 find_all()
1.字串
soup.find_all('b')//查詢所有B標籤
2.正則表示式
for tag in soup.find_all(re.compile("t"))://所有名字當中帶t字母的標籤
print(tag.name)
for tag in soup.find_all(re.compile("^b"))://所有名字以b開頭的標籤
print(tag.name)
3.列表
soup.find_all(["a", "b"])//分別查詢所有的a b 標籤,運用了字串那一類
按CSS搜尋
soup.find_all("a", class_="sister")
soup.find_all("p", class_="body strikeout")
find_all("p", "title") 返回的是CSS Class為”title”的<p>標籤
通過 string 引數可以搜搜文件中的字串內容.與 name 引數的可選值一樣, string 引數接受 字串 , 正則表示式 , 列表, True .
soup.find_all(string="Elsie")
soup.find_all(string=["Tillie", "Elsie", "Lacie"])
soup.find_all(string=re.compile("Dormouse"))
呼叫tag的 find_all() 方法時,Beautiful Soup會檢索當前tag的所有子孫節點,如果只想搜尋tag的直接子節點,可以使用引數 recursive=False .
soup.html.find_all("title", recursive=False)
soup.find_all('title', limit=1) 等價於 soup.find('title')
limit 引數限制返回結果的數量只找鄰近的一個
.select() 方法
在 Tag 或 BeautifulSoup 物件的 .select() 方法中傳入字串引數, 即可使用CSS選擇器的語法找到tag通過tag標籤逐層查詢:
soup.select("body a")
soup.select("html head title")
直接子標籤
soup.select("p > a")
兄弟節點標籤:
soup.select("#link1 ~ .sister")
通過tag的id查找
soup.select("#link1")
通過CSS的類名查找
soup.select(".sister")
soup.select("[class~=sister]")
soup.get_text("|")//分隔符
編碼
任何HTML或XML文件都有自己的編碼方式,比如ASCII 或UTF-8,但是使用Beautiful Soup解析後,文件都被轉換成了Unicode:
通過傳入 from_encoding 引數來指定編碼方式:
soup = BeautifulSoup(markup, from_encoding="iso-8859-8")
. (exclude_encodings 引數是4.4.0版本的新功能)排除,這樣文件就不會嘗試使用這種編碼瞭解碼
兩個 NavigableString 或 Tag 物件具有相同的HTML或XML結構時, Beautiful Soup就判斷這兩個對象相同.
如果想判斷兩個對象是否嚴格的指向同一個對象可以通過 is 來判斷
copy.copy() 方法可以複製任意 Tag 或 NavigableString 對象
import copy
p_copy = copy.copy(soup.p)
解析部分文件
如果僅僅因為想要查找文件中的<a>標籤而將整片文件進行解析,實在是浪費記憶體和時間.最快的方法是從一開始就把<a>標籤以外的東西都忽略掉. SoupStrainer 類可以定義文件的某段內容,這樣搜尋文件時就不必先解析整篇文件,只會解析在 SoupStrainer 中定義過的文件. 建立一個 SoupStrainer 物件並作為 parse_only 引數給 BeautifulSoup 的構造方法即可.
from bs4 import SoupStrainer
1.only_a_tags = SoupStrainer("a")
2.only_tags_with_id_link2 = SoupStrainer(id="link2")
3.def is_short_string(string):
return len(string) < 10
only_short_strings = SoupStrainer(string=is_short_string)
print(BeautifulSoup(html_doc, "html.parser", parse_only=only_a_tags).prettify())
#引數一為解析的內容,引數二為指定解析器
print(BeautifulSoup(html_doc, "html.parser", parse_only=only_tags_with_id_link2).prettify())
print(BeautifulSoup(html_doc, "html.parser", parse_only=only_short_strings).prettify())
預設情況下,Beautiful Soup會將當前文件作為HTML格式解析,如果要解析XML文件,要在 BeautifulSoup 構造方法中加入第二個引數“xml”:
soup = BeautifulSoup(markup, "xml")
當然,還需要 安裝lxml
還有提高Beautiful Soup效率的辦法,使用lxml作為解析器.Beautiful Soup用lxml做解析器比用html5lib或Python內建解析器速度快很多.
加油吧,程式設計師!