BeautifulSoup中select的使用方法
html = """ <html><head><title>The Dormouse's story</title></head> <body> <p class="title" name="dromouse"><b>The Dormouse's story</b></p> <p class="story">Once upon a time there were three little sisters; and their names were <a href="http://example.com/elsie" class="sister" id="link1"><!-- Elsie --></a>, <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>; and they lived at the bottom of a well.</p> <p class="story">...</p> """
我們在寫 CSS 時,標籤名不加任何修飾,類名(class="className"引號內即為類名)前加點,id名(id="idName"引號前即為id名)前加 #,在這裡我們也可以利用類似的方法來篩選元素,用到的方法是 soup.select(),返回型別是 list
(1)通過標籤名查詢
print soup.select('title') #[<title>The Dormouse's story</title>]
print soup.select(‘a’)
#[<a class=“sister” href=“http://example.com/elsie
print soup.select(‘b’)
#[<b>The Dormouse’s story</b>]
(2)通過類名查詢
print soup.select('.sister') #[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
(3)通過 id 名查詢
print soup.select('#link1') #[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]
(4)組合查詢
組合查詢即和寫 class 檔案時,標籤名與類名、id名進行的組合原理是一樣的,例如查詢 p 標籤中,id 等於 link1的內容,二者需要用空格分開
print soup.select('p #link1') #[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]
直接子標籤查詢
print soup.select("head > title") #[<title>The Dormouse's story</title>]
(5)屬性查詢
查詢時還可以加入屬性元素,屬性需要用中括號括起來,注意屬性和標籤屬於同一節點,所以中間不能加空格,否則會無法匹配到。
print soup.select("head > title") #[<title>The Dormouse's story</title>]
print soup.select(‘a[href=“http://example.com/elsie”]’)
#[<a class=“sister” href=“http://example.com/elsie” id=“link1”><!-- Elsie --></a>]
同樣,屬性仍然可以與上述查詢方式組合,不在同一節點的空格隔開,同一節點的不加空格
print soup.select('p a[href="http://example.com/elsie"]') #[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]
BeautifulSoup支援CSS選擇器是令人驚喜的,這大大方便了我們對特定標籤的選取。那麼接下來就來試驗一下。
比如現在我們需要選取搜狗主頁中導航欄中導向“知乎”的連結。
分析文件結構大概有這幾個比較容易區分的層級特點:
-
<div class="top-nav">
-
<ul>
-
...
-
<li class="cur">
<span>網頁
</span>
</li>
-
href="http://zhihu.sogou.com/" uigs-id="nav_zhihu" id="zhihu">知乎
</a>
</li>
-
<li>
<a onclick="st(this,'40030500','pic')" href="http://pic.sogou.com" uigs-id="nav_pic" id="pic">圖片
</a>
</li>
-
...
-
</ul>
-
</div>
鑑於如此的結構,我們可以使用類選擇器選擇“.top-nav”然後使用後代選擇其選擇“ul”標籤和“li”標籤,於是整個選擇器可以寫為“.top-nav ul li”,在程式碼中實現如下:
-
li = bs.select(
'.top-nav ul li')
-
print(
"result len is", len(li))
-
for tag
in li:
-
print(tag)
得到如下輸出:
-
result len is 10
-
<li>
<a href="http://news.sogou.com" id="news" onclick="st(this,'40030300','news')" uigs-id="nav_news">新聞
</a>
</li>
-
<li class="cur">
<span>網頁
</span>
</li>
-
<li>
<a href="http://weixin.sogou.com/" id="weixinch" onclick="st(this,'73141200','weixin')" uigs-id="nav_weixin">微信
</a>
</li>
-
<li>
<a href="http://zhihu.sogou.com/" id="zhihu" onclick="st(this,'40051200','zhihu')" uigs-id="nav_zhihu">知乎
</a>
</li>
-
<li>
<a href="http://pic.sogou.com" id="pic" onclick="st(this,'40030500','pic')" uigs-id="nav_pic">圖片
</a>
</li>
-
...
但裡面出現了“網頁”這個沒有連結到其他地址的項,要如何將之過濾掉呢。可以結合filter函式進行處理,如下:
-
def hasHttpLink(tag):
-
"""此時的tag為<li>標籤,需要取得其中的<a>再來進行判斷"""
-
return tag.a
is
not
None
and tag.a.get(
'href').startswith(
"http")
-
-
for tag
in filter(hasHttpLink, li):
-
print(tag)
結果中已經過濾掉“網頁”這項了:
-
<li>
<a href="http://news.sogou.com" id="news" onclick="st(this,'40030300','news')" uigs-id="nav_news">新聞
</a>
</li>
-
<li>
<a href="http://weixin.sogou.com/" id="weixinch" onclick="st(this,'73141200','weixin')" uigs-id="nav_weixin">微信
</a>
</li>
-
<li>
<a href="http://zhihu.sogou.com/" id="zhihu" onclick="st(this,'40051200','zhihu')" uigs-id="nav_zhihu">知乎
</a>
</li>
-
<li>
<a href="http://pic.sogou.com" id="pic" onclick="st(this,'40030500','pic')" uigs-id="nav_pic">圖片
</a>
</li>
-
...
其中filter高階函式進行過濾時還可以使用正則來進行匹配篩選。
不過一般情況下僅僅使用selector就能比較精確的獲取結果集了,因此filter也不用寫得很複雜。