一、beautiful soup 是Python的一個HTML或XML的解析庫。
他提供一個簡單的、Python式的函數來處理導航、搜索、修改分析數等功能。它是一個工具箱,通過解析文檔為用戶提供需要抓取的數據,因為簡單,所以不需要多少代碼就可以寫出一個完整的應用程序。
beautiful soup 自動將輸入文檔轉化為Unicode編碼,輸出文檔轉化為utf-8編碼。你不需要考慮編碼方式,除非文檔沒有指定一個編碼方式,這時你僅僅需要說明一下原始的編碼方式就可以了。
from bs4 import BeautifulSoup soup=BeautifulSoup('<p>hello</p>','lxml')
print(soup.p.string)
# 返回了p標簽的內容
html=‘<html>
<head><title>story</title></head>
<body><div>
<p class='t1' name='t2'>我的天,蒙蔽了</p>
</div></body>'
from bs4 import BeautifulSoup
soup=BeautifulSoup(html,'lxml')
print(soup.prettiful()) #例子的html節點沒有閉合 缺少標簽</html> 返回的完整html不是prettiful做的是初始化BeautifulSoup時就完成了
print(soup.title.string) #返回標題的內容
print(soup.title) #返回的是<title>story</title>
print(soup.head) #<head><title>story</title></head>
prinp(soup.p) #<p>我的天,蒙蔽了</p>
#當有多個屬性時,此種方法只能獲取第一個匹配的節點
二、提取信息
上面演示了調用string屬性來獲取文本的值,那么如何獲得節點屬性的值?
(1)可以利用name屬性獲取幾點的名稱,這里還是以上面文本為例,選取title節點然后調用name屬性就可以獲得節點名稱
print(soup.title.name) #title 不懂為什么出這個命令 我可能看不出來吧
(2)獲取屬性
每個節點都可能有多個屬性,比如id和class等,選擇這個節點后,可以調用class獲取所有屬性
print(soup.p.attrs)
print(soup.p.attrs['name']
運行結果如下:
{'class':['t1'],'name':'t2'}
['t2']
另
print(soup.p['class']
print(soup.p['name']
獲取需要的屬性
(3)獲取內容
可以利用string獲取內容
print(soup.p.string)
三、
(1)嵌套選擇
上面的語句中返回的都是bs4.element.Tag類型。
所謂嵌套的意思是通過第一個,可以一直找到此節點下的最后一個屬性。
ex:
print(soup.head.title.string)
(2)關聯選擇
在做選擇時,有時候不能做到一步就選到想要的節點元素。需要以他為基點,再選擇它的子節點、父節點、兄弟節點等。
子節點和子孫節點
html=''
from bs4 import BeautifulSoup
soup=BeautifulSoup(html,'lxml')
print(soup.p.contents) #打印的是p節點下的所有節點與內容 包括\n 的一個列表
還可以用children屬性得到相應的結果
from bs4 import BeautifulSoup
soup=BeautifulSoup(html,'lxml')
print(soup.p.children) 得到的是一個生成器所以要想得到結果怎么辦呢?<list_iterator object at 0x00000000029C8E80>
for i,child in enumerate(soup.p.children):
print(i,child)
用descendants 得到p節點下的所有屬性 包括吧節點<a>aaaa</a>中的內容單獨提出來
得到的也是一個生成器需要 去想辦法得到其需要的東西
父節點和祖先節點
print(soup.a.parent)
獲取選擇的a節點的第一個父節點 直接其節點的代碼
print(soup.a.parents)
獲得的是a節點外的所有祖先節點 返回的是一個生成器
兄弟節點
print(soup.a.next_sibling) 獲取節點的下一個兄弟元素
print(soup.a.previous_sibling) 獲取節點的上一個兄弟元素
print(list(enumerate(soup.a.next_siblings))) 獲取所有的a節點以后的所有兄弟節點
print(list(enumerate(soup.a.previous_siblings))) 獲取所有的a節點以前所有的兄弟節點
方法選擇器
find_all() 就是查找所有符合屬性的元素,給他傳入一些條件就傳出,所有符合跳進的元素
它返回的是一個列表,
print(soup.find_all(name='ul')
還可以進行嵌套查詢,例如查詢里面的li節點
for ul in soup.find_all(name='ul'):
print(ul.find_all(name='li'))
for li in ul.find_all(name='li;)
print(li.string)
返回了li的所有文本內容
attrs()
除了根據節點名查詢,
print(soup.find_all(attrs={'id':'name1'}))
print(soup.find_all(attrs={'name':'elements'}))
這里查詢的時候傳入的是attrs參數,參數的類型是字典類型,,得到結果是列表形式,包含的內容就是符合條件的節點。
對於一些常用的屬性,比如id class 等 我們可以不用attrs來傳遞。
ex:
from bs4 import BeautifulSoup
soup=Beautiful(html,'lxml')
print(soup.find_all(id='index'))
print(soup.find_all(class_='element'))
注意:由於class是Python的關鍵字,所以在這里的class用class_ 來代替
返回的結果依然是列表
text 參數可以用來匹配節點的文本,傳入的形式可以是字符串,可以使正則表達式對象。
返回的是文本,不包括節點。
find()
除了find_all()外還有find()方法,只不過后者返回的是單個元素,也就是第一個匹配的元素,而前者返回的是所有匹配的元素組成的列表。
還有很多查詢方法:
find_parents()find_parent() 返回所有符合條件的祖先節點/一個
find_next_siblings() find_next_sibling() 后面的兄弟節點
find_previous_siblings() find_previous_siblings() 前面的兄弟節點
find_all_next() find_next() 返回所有后面符合條件的節點 一個
find_all_previous find_previous() 返回所有前面符合條件的節點 一個
CSS選擇器
熟悉web開發的肯定熟悉選擇器,不熟悉,請自行學習。
使用選擇器時,調用select(),傳入相應的css選擇器即可。
ex:
print(soup.select('.first .second)) 類選擇器
print(soup.select('div ul') 標簽選擇器
print(soup.select('#id .first)) id選擇器 加類選擇器
輸出的都是列表
嵌套選擇:
from bs4 import BeautifulSoup
soup=BeautifulSoup(html,'lxml')
for ul in soup.select('ul'):
print(ul.select('li')) 獲ul中的li節點
print(ul['id]) 獲取屬性
print(ul.attrs['id']) 獲取屬性
獲取文本
print(soup.select('li').get_text())
print(soup.select('li').string()) 它倆的效果一致
總結:
推薦使用lxml,必要時使用lxml.parser
節點選擇篩選功能弱,但速度塊
建議使用find() find_all()查詢單個或者多個結果
css選擇器也是個不錯的選擇