beautifulsoup就是一個非常強大的工具,爬蟲利器。beautifulSoup “美味的湯,綠色的濃湯”
一個靈活又方便的網頁解析庫,處理高效,支持多種解析器。利用它就不用編寫正則表達式也能方便的實現網頁信息的抓取
bs4簡單使用
- bs4是一個html的解析工具,根據html的特征和屬性來查找節點
1 from bs4 import BeautifulSoup 2 3 fp = open("./test.html", "r", encoding="utf-8") 4 print(fp)
- 初始化一個BeautifulSoup對象
1 soup = BeautifulSoup(fp, 'lxml') 2 # 參數1,是一個HTML字符串 3 # 參數2,代表一個解析器,因為bs4本身沒有解析器,可以借助於外界的解析器來解析 5 print(soup)
- 1、根據標簽來查找對象
1 print(soup.title) 2 print(soup.a) # 如果標簽有多個,只提取第一個
- 2、獲取標簽的屬性
1 a = soup.a 2 print(a.get("href")) # 用get函數來獲取 3 print(a["href"]) # 用鍵值方式獲取 4 print(a.attrs)
- 3、獲取內容
1 li = soup.li 2 print(li.string) # 通過string屬性獲取,可以獲取當前標簽的字符串內容(包括注釋),但是如果當前內容中有子標簽則獲取為空 3 print(li.get_text()) # 通過get_text函數獲取,獲取出當前節點的字符串和后代節點中所有的字符串並且拼接在一起,但是如果有注釋則忽略
- 4、獲取后代節點
1 body = soup.body 2 3 # 1)獲取直接子節點 4 children = body.children 5 print(children) # 打印結果:<list_iterator object at 0x0000026E8ED16080> 6 7 # 2)獲取后代節點 8 des = body.descendants 9 print(des) # 打印結果:<generator object descendants at 0x00000203556CD048>
- 5、獲取兄弟節點
1 soup.a.next_siblings 獲取后面的兄弟節點 2 soup.a.previous_siblings 獲取前面的兄弟節點 3 soup.a.next_sibling 獲取下一個兄弟標簽 4 souo.a.previous_sinbling 獲取上一個兄弟標簽
- 6、獲取父親節點
1 通過 soup.a.parent 可以獲取父節點的信息 2 3 通過 list(enumerate(soup.a.parents)) 可以獲取祖先節點, 4 5 這個方法返回的結果是一個列表,會分別將a標簽的父節點的信息存放到列表中, 6 以及父節點的父節點也放到列表中,並且最后還會講整個文檔放到列表中, 7 所有列表的最后一個元素以及倒數第二個元素都是存的整個文檔的信息
- 7、用函數來查找
1 # 1)find函數 2 print(soup.find("a")) 3 print(soup.find("li",class_='hehe')) 4 print(soup.find("li",id='hehe')) 5 6 # 2)find_all函數 7 print(soup.find_all("a")) 8 9 # 3) select函數,根據css選擇器來選取節點,返回值是一個列表 10 print(soup.select(".heihei")) 11 print(soup.select("#hehe")) 12 print(soup.select("[href='http://mi.com']")) 13 print(soup.select("[name='ok']"))
- 基礎選擇器:id選擇器,#id值。class選擇器,.class值。標簽選擇器,標簽名。通用選擇器,*。屬性選擇器 [某屬性='某值']
- 組合選擇器:選擇器1選擇器2...選擇器n (如果這些選擇器中有標簽要放在最前面)
- 派生選擇器:后代選擇器:選擇器1 選擇器2 ... 選擇器n
- 子選擇器: 選擇器1 > 選擇器2 > ... > 選擇器n
解析器
Beautiful Soup支持Python標准庫中的HTML解析器,還支持一些第三方的解析器,如果我們不安裝它,
則 Python 會使用 Python默認的解析器,lxml 解析器更加強大,速度更快,推薦安裝。
推薦使用lxml作為解析器,因為效率更高. 在Python2.7.3之前的版本和Python3中3.2.2之前的版本,
必須安裝lxml或html5lib, 因為那些Python版本的標准庫中內置的HTML解析方法不夠穩定
基本使用
標簽選擇器
print(soup.p) 通過 soup.標簽名 可以獲得這個標簽的內容
獲取名稱
通過soup.title.name 可以獲得該title標簽的名稱,即title
獲取屬性
print(soup.p.attrs['name'])
print(soup.p['name'])
上面兩種方式都可以獲取p標簽的name屬性值
獲取內容
print(soup.p.string) 結果就可以獲取第一個p標簽的內容
嵌套選擇
print(soup.head.title.string) 通過嵌套的方式獲取
標准選擇器
find_all
find_all(name,attrs,recursive,text,**kwargs). 可以根據標簽名,屬性,內容查找文檔
find
find(name,attrs,recursive,text,**kwargs) find返回的匹配結果的第一個元素
其他
find_parents()返回所有祖先節點,find_parent()返回直接父節點。
find_next_siblings()返回后面所有兄弟節點,find_next_sibling()返回后面第一個兄弟節點。
find_previous_siblings()返回前面所有兄弟節點,find_previous_sibling()返回前面第一個兄弟節點。
find_all_next()返回節點后所有符合條件的節點, find_next()返回第一個符合條件的節點
find_all_previous()返回節點后所有符合條件的節點, find_previous()返回第一個符合條件的節點
參數
name的用法

1 html=''' 2 <div class="panel"> 3 <div class="panel-heading"> 4 <h4>Hello</h4> 5 </div> 6 <div class="panel-body"> 7 <ul class="list" id="list-1"> 8 <li class="element">Foo</li> 9 <li class="element">Bar</li> 10 <li class="element">Jay</li> 11 </ul> 12 <ul class="list list-small" id="list-2"> 13 <li class="element">Foo</li> 14 <li class="element">Bar</li> 15 </ul> 16 </div> 17 </div> 18 ''' 19 from bs4 import BeautifulSoup 20 soup = BeautifulSoup(html, 'lxml') 21 print(soup.find_all('ul')) 22 print(type(soup.find_all('ul')[0]))
結果返回的是一個列表的方式。同時我們是可以針對結果再次find_all,從而獲取所有的li標簽信息
1 for ul in soup.find_all('ul'): 2 print(ul.find_all('li'))
attrs
attrs可以傳入字典的方式來查找標簽,但是這里有個特殊的就是class,因為class在python中是特殊的字段,所以如果想要查找class相關的可以更改attrs={'class_':'element'}或者soup.find_all('',{"class":"element}),特殊的標簽屬性可以不寫attrs,例如id

1 html=''' 2 <div class="panel"> 3 <div class="panel-heading"> 4 <h4>Hello</h4> 5 </div> 6 <div class="panel-body"> 7 <ul class="list" id="list-1" name="elements"> 8 <li class="element">Foo</li> 9 <li class="element">Bar</li> 10 <li class="element">Jay</li> 11 </ul> 12 <ul class="list list-small" id="list-2"> 13 <li class="element">Foo</li> 14 <li class="element">Bar</li> 15 </ul> 16 </div> 17 </div> 18 ''' 19 from bs4 import BeautifulSoup 20 soup = BeautifulSoup(html, 'lxml') 21 print(soup.find_all(attrs={'id': 'list-1'})) 22 print(soup.find_all(attrs={'name': 'elements'}))
text
結果返回的是查到的所有的text='Foo'的文本

1 html=''' 2 <div class="panel"> 3 <div class="panel-heading"> 4 <h4>Hello</h4> 5 </div> 6 <div class="panel-body"> 7 <ul class="list" id="list-1"> 8 <li class="element">Foo</li> 9 <li class="element">Bar</li> 10 <li class="element">Jay</li> 11 </ul> 12 <ul class="list list-small" id="list-2"> 13 <li class="element">Foo</li> 14 <li class="element">Bar</li> 15 </ul> 16 </div> 17 </div> 18 ''' 19 from bs4 import BeautifulSoup 20 soup = BeautifulSoup(html, 'lxml') 21 print(soup.find_all(text='Foo'))
CSS選擇器
通過select()直接傳入CSS選擇器就可以完成選擇,熟悉前端的人對CSS可能更加了解,其實用法也是一樣的
.表示class #表示id
標簽1,標簽2 找到所有的標簽1和標簽2
標簽1 標簽2 找到標簽1內部的所有的標簽2
[attr] 可以通過這種方法找到具有某個屬性的所有標簽
[atrr=value] 例子[target=_blank]表示查找所有target=_blank的標簽

1 html=''' 2 <div class="panel"> 3 <div class="panel-heading"> 4 <h4>Hello</h4> 5 </div> 6 <div class="panel-body"> 7 <ul class="list" id="list-1"> 8 <li class="element">Foo</li> 9 <li class="element">Bar</li> 10 <li class="element">Jay</li> 11 </ul> 12 <ul class="list list-small" id="list-2"> 13 <li class="element">Foo</li> 14 <li class="element">Bar</li> 15 </ul> 16 </div> 17 </div> 18 ''' 19 from bs4 import BeautifulSoup 20 soup = BeautifulSoup(html, 'lxml') 21 print(soup.select('.panel .panel-heading')) 22 print(soup.select('ul li')) 23 print(soup.select('#list-2 .element')) 24 print(type(soup.select('ul')[0]))
獲取內容
通過get_text()就可以獲取文本內容

1 html=''' 2 <div class="panel"> 3 <div class="panel-heading"> 4 <h4>Hello</h4> 5 </div> 6 <div class="panel-body"> 7 <ul class="list" id="list-1"> 8 <li class="element">Foo</li> 9 <li class="element">Bar</li> 10 <li class="element">Jay</li> 11 </ul> 12 <ul class="list list-small" id="list-2"> 13 <li class="element">Foo</li> 14 <li class="element">Bar</li> 15 </ul> 16 </div> 17 </div> 18 ''' 19 from bs4 import BeautifulSoup 20 soup = BeautifulSoup(html, 'lxml') 21 for li in soup.select('li'): 22 print(li.get_text())
獲取屬性
或取屬性的時候可以通過[屬性名]或者attrs[屬性名]

1 html=''' 2 <div class="panel"> 3 <div class="panel-heading"> 4 <h4>Hello</h4> 5 </div> 6 <div class="panel-body"> 7 <ul class="list" id="list-1"> 8 <li class="element">Foo</li> 9 <li class="element">Bar</li> 10 <li class="element">Jay</li> 11 </ul> 12 <ul class="list list-small" id="list-2"> 13 <li class="element">Foo</li> 14 <li class="element">Bar</li> 15 </ul> 16 </div> 17 </div> 18 ''' 19 from bs4 import BeautifulSoup 20 soup = BeautifulSoup(html, 'lxml') 21 for ul in soup.select('ul'): 22 print(ul['id']) 23 print(ul.attrs['id'])