BeautifulSoup主要介紹與基礎爬蟲專案實踐
強大的BeautifulSoup
1.簡要介紹
BeautifulSoup是一個可以從HTML或XML檔案中提取資料的Python庫,它能夠通過你喜歡的轉換器實現慣用的文件導航,查詢,修改文件的方式。
2.Beautiful Soup的安裝
方法1: pip install bs4
方法2:在Pycharm中,可以在File -> Settings -> Project Interpreter -> 右側有個加號按鈕 -> 在彈出的視窗搜尋bs4並安裝。
3.BeautifulSoup的使用
[0].bs4庫的匯入
from bs4 import BeautifulSoup
[1].建立BeautifulSoup物件
以下'lxml'是手動指定的解析器。如果省略,BeautifulSoup一般會選擇最合適的解析器來解析這段文件,如果手動指定,那麼BeautifulSoup會選擇指定的解析器來解析文件。
方式1. 直接通過字串建立
soup = BeautifulSoup(html_str, 'lxml', from_encoding = 'utf-8')
Example:
from bs4 import BeautifulSoup
import requests
import chardet
url = 'http://www.baidu.com'
response = requests.get(url)
response.encoding = chardet.detect(response.content)['encoding']
text = response.text
soup = BeautifulSoup(text, 'lxml')
print(soup.prettify())
方式2. 通過html檔案來建立
from bs4 import BeautifulSoup
import requests
import chardet
url = 'http://www.baidu.com'
response = requests.get(url)
response.encoding = chardet.detect(response.content)['encoding']
text = response.text
with open('hell', 'w') as fout:
fout.write(text)
soup = BeautifulSoup(open('hell'), 'lxml')
print(soup.prettify())
[2].物件種類
BeautifulSoup將複雜HTML文件轉換成一個複雜的樹形結構,每個節點都是Python物件,所有物件可以歸納為4種:
a. Tag
b. NavigableString
c. BeautifulSoup
d. Comment
1). Tag
Tag物件與XML或HTML原生文件中的Tag相同,通俗點說就是標記。標記及其裡面的內容稱為Tag物件。
import requests
import chardet
url = 'http://www.baidu.com'
response = requests.get(url)
response.encoding = chardet.detect(response.content)['encoding']
text = response.text
with open('hell', 'w') as fout:
fout.write(text)
soup = BeautifulSoup(open('hell'), 'lxml')
# print(soup.prettify())
print(soup.title)
print(soup.a)
Result:
<title>百度一下,你就知道</title>
<a class="mnav" href="http://news.baidu.com" name="tj_trnews">新聞</a>
從栗子中可以看出,利用soup加標記名就可以很容易這些標記的內容,比之前講的正則表示式簡單多了。不過利用這種方式,查詢的時所有內容中第一個符合要求的標記。
Tag中有兩個最重要的屬性:name和atrributes。
.name
每個Tag都有自己的名字,通過.name來獲取
print( soup.name )
print( soup.title.name )
Result:
[document]
title
soup物件本身比較特殊,它的name為[document],對於其他內部標記,輸出的值便是標記本身的名稱。
Tag不僅可以獲取name,還可以修改name,改變之後將影響所有通過當前BeautifulSoup物件生成的HTML文件。
soup.title.name = 'mytitle'
print( soup.title )
print( soup.mytitle )
Result:
None
<mytitle>百度一下,你就知道</mytitle>
屬性:
Tag的屬性的操作方法與字典相同,直接獲取; 也可以直接‘點’取屬性,.attrs,用於獲取Tag中的所有屬性。
print( soup.a['href'] )
print( soup.a.attrs['href'] )
2).NavigableString
我們已經得到了標記的內容,要想獲取標記內部的文字怎麼辦呢?需要用到.string
Example:
print( soup.title.string )
print( type(soup.title.string) )
Result:
百度一下,你就知道
<class 'bs4.element.NavigableString'>
注:BeautifulSoup用NavigableString類來包裝Tag中的字串,一個Navigable字串與Python中的Unicode字串相同。
3).BeautifulSoup物件表示的是一個文件的全部內容。大部分時候,可以把它當作Tag物件,是一個特殊的Tag物件,因為BeautifulSoup物件並不是真正的HTML或XML的標記,所以它沒有name和attribute屬性。但為了將BeautifulSoup物件標準化為Tag物件,實現介面的統一,我們依然可以分別獲取它的name和attribute屬性。
4).Comment
Tag, NavigableString, BeautifulSoup幾乎覆蓋了HTML和XML中的所有內容,但是還是有些特殊物件。容易讓人擔心的內容是文件的註釋部分:如果不清楚這個標記.string的情況下,可能會造成資料提取混亂。
[3].遍歷文件樹
×××重中之重
[4].搜尋文件樹
BeautifulSoup定義了很多搜尋方法,這裡著重介紹find_all()方法,其他方法的引數和用法類似,請大家舉一反三。
find_all方法,用於搜尋當前Tag的所有Tag子節點,並判斷是否符合過濾器的條件,函式原型如下:
find_all(name, attrs, recursive, text, **kwargs)
1).name引數
name引數可以查詢所有名字為name的標記,字串物件會被自動忽略掉。name引數值可以是字串,正則表示式,列表,True和方法。
字串:print( soup.find_all('a') )
正則表示式:print( soup.find_all(re.compile('^b')) )
列表:print( soup.find_all(['a', 'b']) )
True: print( soup.find_all(True) )
2).kwargs引數
kwargs引數在Python裡表示為keyword引數。如果一個指定名字的引數不是搜尋內建的引數名
[5].CSS選擇器
我們也可以利用CSS選擇器來篩選元素,在寫CSS時,標記名前不加任何修飾,類名前加‘.’, id前加‘#’。用到的方法是soup.select(),返回型別時list。
1).通過標記名稱進行查詢
# 直接查詢title標記
print( soup.select('title') )
# 逐層查詢title標記
print( soup.select('html head title') )
# 查詢直接子節點
# 查詢head下的title標記
print( soup.select('head > title') )
# 查詢p下的id="link1"的標記
print( soup.select('p > #link1') )
#查詢兄弟節點
#查詢id='link1'之後class=sister的所有兄弟標記
print( soup.select('#link1 ~ .sister') )
#查詢緊跟id = 'link1' 之後class=sister的子標記
print( soup.select('#link1 + .sister') )
2).通過CSS的類名查詢
print( soup.select('.sister') )
print( soup.select('[class~=sister]') )
3).通過tag的id查詢
print( soup.select('#link1') )
print( soup.select('a#link2') )
4).通過是否存在某個屬性來查詢
print( soup.select('a[href]') )
5).通過屬性值來查詢
Tag[attribute] 用於選取帶有指定屬性的元素
Tag[attribute=value] 用於選取帶有指定屬性和值的元素
Tag[attribute~=value] 用於選取屬性值中包含指定詞彙的元素
Tag[attribute|=value] 用於選取帶有以指定值開頭的屬性值的元素,該值必須是整個單詞
Tag[attribute^=value] 匹配屬性值以指定值開頭的每個元素
Tag[attribute$=value] 匹配屬性值以指定值結尾的每個元素
Tag[attribute*=value] 匹配屬性值中包含指定值的每個元素