從網絡上獲取網頁內容以後,需要從這些網頁中取出有用的信息,畢竟爬蟲的職責就是獲取有用的信息,而不僅僅是爲了下來一個網頁。獲取網頁中的信息,首先需要指導網頁內容的組成格式是什麼,沒錯網頁是由 HTML「我們成爲超文本標記語言,英語:HyperText Markup Language,簡稱:HTML」 組成的,其次需要解析網頁的內容,從中提取出我們想要的信息。
HTML
超文本標記語言(英語:HyperText Markup Language,簡稱:HTML)是一種用於創建網頁的標準標記語言。HTML是一種基礎技術,常與CSS、JavaScript一起被衆多網站用於設計網頁、網頁應用程序以及移動應用程序的用戶界面[3]。網頁瀏覽器可以讀取HTML文件,並將其渲染成可視化網頁。HTML描述了一個網站的結構語義隨着線索的呈現,使之成爲一種標記語言而非編程語言。
以上內容摘自維基百科,它將網頁的組成做了一個簡單且明確的解釋,從中我們知道 HTML、CSS、JavaScript 是一個網頁的重要組成部分。但是對於一個爬蟲來說它需要關注的僅僅只是 HTML,無需過多關注 CSS 和 JavaScript。
CSS 用於網頁的顯示格式,爬蟲不關注顯示的格式。JavaScript 主要用於動態加載內容,當前可暫不關注。
HTML 文檔主要有 HTML 元素「或者標籤」組成,常用的 HTML 標籤主要有以下幾種:
- <html> 用來定義一個 HTML 文檔。
- <head> 用來定義 HTML 文檔的信息。
- <body> 定義 HTML 文檔的主體。
- <h1> 到 <h6> 定義 HTML 標題。
- <form> 定義 HTML 文檔表單。
- <p> 定義一個段落。
- <a> 定義一個超文本連接。
- <div> 定義文檔中的一個節。
HTML 標籤遠不止上面的這幾種,這裏只是列出了常見的幾種,大家可以在網上找到很多這方面的內容「從網絡上找到自己想要的內容,也是一種重要的能力」。
除了標籤以外,屬性也是 HTML 的一個重要組成部分。屬性以“名稱-值”的形式成對出現,由“=”分離並寫在開始標籤元素名之後,對每個標籤的顯示方式及顯示狀態進行控制。常用的屬性主要有以下幾種:
- id 屬性爲元素提供了在全文檔內的唯一標識。它用於識別元素,以便樣式表可以改變其表現屬性,腳本可以改變、顯示或刪除其內容或格式化。
- class 屬性提供一種將類似元素分類的方式。常被用於語義化或格式化。
- style 屬性可以將表現性質賦予一個特定元素
- title 屬性用於給元素一個附加的說明。 大多數瀏覽器中這一屬性顯示爲工具提示。
我們通過 HTML 文檔中的標籤和屬性來確定一個內容的位置,從而獲取我們需要從網頁上讀取內容。
網頁內容的解析
網頁實際上就是一個 HTML 文檔,網頁內容的解析實際上就是對 HTML 文檔的解析,在 python 中我們可以使用正則表達式 re,BeautifulSoup、Xpath等網頁解析工具來實現對網頁內容的解析。這裏主要介紹 BeautifulSoup 的使用。
今天主要介紹 BeautfulSoup 的以下內容:
- string、strings 和 stripped_strings: BeautifulSoup 通過這三個屬性來獲取 Tag 的內容。
- find 和 find_all:搜索當前 Tag 及其所有子節點,判斷其是否符合過濾條件。
如果一個 Tag 僅有一個子節點有內容「NavigableString 類型子節點」或其只有一個子節點可以使用 string 屬性來獲取節點內容。若 Tag 包含多個子節點,且不止一個子節點含有內容,此時需要用到 strings 和 stripped_strings 屬性,使用 strings 獲取的內容會包含很多的空格和換行,使用 stripped_strings 可以過濾這些空格和換行。
通過 find 和 find_all 方法可以過濾掉不需要的字符串對象,使用示例如下:
# -*- coding:utf-8 -*-
from bs4 import BeautifulSoup
import re
html = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>and
<a class="sister" href="http://example.com/tillie" id="link2">Tillie</a>;
and they lived at the bottom of a well.
</p>
</body>
</html>
"""
soup = BeautifulSoup(html, features='lxml')
print ('---------- string ----------')
print (soup.find_all('title'))
print ('---------- regex ----------')
print (soup.find_all(re.compile('^b')))
print ('---------- list ----------')
print (soup.find_all(['b', 'a']))
print ('---------- True ----------')
print (soup.find_all(True))
print ('---------- function ----------')
def has_class_but_no_href(tag):
return tag.has_attr('class') and not tag.has_attr('href')
print (soup.find_all(has_class_but_no_href))
現在需要從以上的網頁中解析出品牌、廠家型號、商品編號、封裝規格等內容,該怎麼做?首先先確定一下它所對應的 HTML 文檔的內容
從以上 HTML 文檔內容中,可以看出索要獲取的內容在 <div class="product_brand_con"> 的小節中,那麼需要使用 find 方法從整個 HTML 文檔中先把這個小節提取出來,然後使用 find_all 提取出所有的 <div class="item"> 的內容,最後使用 string 屬性獲取對應的字符串內容。整個過程使用代碼表示如下:
brand_dict = {}
soup = soup.find('div', class_='product_brand_con')
if soup is None:
return brand_dict
soup = soup.find_all('div', class_='item')
for item in soup:
str = []
for stri in item.stripped_strings:
str.append(stri)
if len(str) < 2:
continue
if str[0] == '品 牌:':
brand_dict['brand'] = str[1]
if str[0] == '廠家型號:':
brand_dict['model'] = str[1]
if str[0] == '商品編號:':
brand_dict['number'] = str[1]
if str[0] == '封裝規格:':
brand_dict['package'] = str[1]
以上代碼最終返回一個包含所需內容的字典,若該網頁中不存在所需內容將返回一個空字典。
有關 BeautifulSoup 的更多內容,請看 Python 爬蟲之網頁解析庫 BeautifulSoup 這篇文章。
對網頁內容的解析實際上就是對 HTML 文檔的分割讀取,藉助於 BeautifuSoup 庫,可以非常簡單的從複雜的 HTML 文檔中獲取所需要的內容。