1. 程式人生 > >Python BeautifulSoup4 select方法執行css選擇器

Python BeautifulSoup4 select方法執行css選擇器

初識爬蟲,使用urllib結合強大的BeautifulSoup簡單寫了下程式碼。看參考書上主要講解了find方法的使用,但發現其是還支援css選擇器語法選擇,於是試驗了一下。

環境為:ubuntu12.04 + pycharm2017.1.3 + python3.6 + urllib + beautifulsoup4

構造BeautifulSoup物件

首先,我是以爬取搜狗搜尋的主頁來試驗的。其結構大概如此
搜狗主頁結構

編寫爬蟲程式碼如下

from urllib import request
from bs4 import BeautifulSoup

html = request.urlopen("https://www.sogou.com/"
) #執行請求 bs = BeautifulSoup(html) #將請求結果傳遞給bs構造物件 print(bs.getText) #輸出整個bs的內容

程式碼很簡單清晰,只是將bs物件構造處理直接輸出其內容。當然這體現不出BeautifulSoup的強大,因為這直接通過html物件也能得到。但不要心急,接下來讓我們繼續試驗BeautifulSoup的CSS選擇器功能。

使用BeautifulSoup select方法提取內容

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也不用寫得很複雜。