回顧
在《Python/ target=_blank class=infotextkey>Python進階記錄之urllib模塊》中,我們介紹了Python內置的HTTP請求庫urllib模塊的基本用法,需要重點掌握使用urllib的request模塊進行簡單的get、post請求。今天我們講一下Python內置的html解析庫HTMLParser模塊,并結合之前的re模塊和urllib模塊實現爬取指定新聞頁提取新聞文本內容的小需求。
HTMLParser模塊簡介
我們使用urllib模塊進行HTTP請求獲取到的是整個網頁的HTML,但是我們往往只需要其中一部分對我們有用的內容。這時我們就可以使用HTMLParser模塊來幫助我們處理HTML。
HTMLParser是Python內置的專門用來解析HTML的模塊。利用HTMLParser,我們可以分析出一段HTML里面的標簽、數據等,是一種處理HTML的簡便途徑。我們先來看一個官方的例子。

HTMLParser模塊官方例子
從上述代碼中可以看出,HTMLParser模塊來自html.parser,導包時要格外注意。使用HTMLParser時,我們需要定義一個繼承自HTMLParser的子類,并根據需要重寫HTMLParser父類中的成員方法。例子中使用的各方法作用如下:
handle_starttag(tag, attrs):識別HTML的開始標簽,例如<html>、<title>、<body>、<div>等。
handle_endtag(tag):識別HTML的結束標簽,例如</html>、</body>、</div>、</p>等。
handle_data(data):識別HTML標簽內容,例如“<p>Test</p>”中的Test。
handle_startendtag(tag, attrs):識別沒有結束標簽的HTML標簽,例如<img />等。
handle_comment(data):識別HTML中的注釋內容,一般是“<!-- 注釋 -->”中的注釋內容。
HTMLParser采用的是一種事件驅動的模式,HTMLParser找到一個特定的標記時,它會去調用一個用戶定義的函數,以此來通知程序處理。
我們可以利用這些方法來實現HTML解析相關的功能。其中參數tag表示的是HTML標簽,attrs是一個列表,列表元素為一個個“(屬性,值)”形式的元組。HTMLParser會自動將tag和attrs都轉為小寫,解析時調用feed( )方法,把待解析的HTML字符串傳入即可。
HTMLParser模塊的簡單應用
現在有以下網頁,我們需要獲取出里面的新聞文本內容。

待請求網頁
首先就是獲取該網頁的HTML。經過上節內容的學習,我們很容易想到利用urllib庫請求獲取這個網頁的HTML。

獲取網頁HTML
代碼很簡單,使用urlopen( )方法,傳入url即可。此時,我們已經得到了整個網頁的HTML,但是我們要獲取的是新聞內容,顯然此時的HTML中有太多我們不需要的東西。
觀察整個網頁HTML,我們發現新聞內容是包含在一個div中的。

新聞內容相關HTML
我們可以使用正則表達式re模塊將包含新聞內容的這個div提取出來。

提取新聞內容相關的HTML
新聞內容的div格式主要是:<div class="article-content">...</div>。由于該div下嵌套了其他div,如果我們直接使用r'<div class="article-content">(.*?)</div>'進行正則提取,會發現在下一個</div>處就截斷了。為了正確提取所有新聞內容相關的HTML,我們需要在</div>前加一個</p>,以保證是在新聞內容結束的</div>處截斷。
此時,我們已經得到了新聞內容相關的HTML。現在還剩最后一部,就是把HTML標簽去掉,保留新聞文本內容。這一步,我們就可以利用HTMLParser來實現了。

HTMLParser提取新聞內容
我們定義一個繼承自HTMLParser的子類,然后重寫handle_data(data)方法獲取當前HTML中的文本內容即可。由于我們定義的私有變量__text是通過一個列表來逐條接收新聞內容的,所以我們在類中定義一個獲取私有變量__text的方法,并將列表轉換成字符串。至此,我們已經獲取到了新聞的文本內容。
然而,當前文本內容一整段在一起,看起來并不美觀,與實際分段的新聞文本內容也有差別。我們可以使用HTMLParser來美化新聞內容。我們知道,網頁上的新聞內容是通過“n”、“t”、“<br/>”等特殊符號或標簽進行間隔和分段的。因此,我們只需要在解析時替換掉這些特殊符號和標簽即可。

替換特殊符號和標簽
重寫handle_data(data)方法,識別文本的同時替換掉“t”、“r”、“n”等特殊字符;重寫handle_starttag(tag, attrs)方法,識別出<p>、<br>進行替換;重寫handle_startendtag(tag, attrs)方法,識別出<br/>進行替換。再次運行程序,可以看到,新聞內容進行了分段,看起來就美觀多了。
上述過程實現了一個非常簡單的爬蟲,爬取新聞網頁,提取新聞內容。當然,由于我們目前還沒介紹其他第三方庫,實現起來還不夠靈活,例如獲取新聞內容的div我們現在只能通過正則表達式實現,但實際上,如果使用lxml(etree、xpath)、BeautifulSoup等第三方庫會更簡單實用。
總結
以上內容介紹了Python內置的HTML解析庫HTMLParser模塊,需要重點掌握HTMLParser類常用方法的作用,能夠重寫這些方法進行自定義解析。感謝大家的支持與關注,歡迎一起學習交流~