標籤:urllib BeautifulSoup
思考“網路爬蟲”時通常的想法:
? 通過網站網域名稱擷取 HTML 資料
? 根據目標資訊解析資料
? 儲存目標資訊
? 如果有必要,移動到另一個網頁重複這個過程
當網路瀏覽器遇到一個標籤時,比如<img src="cuteKitten.jpg">,會向伺服器發起另一個請求,以擷取cuteKitten.jpg檔案中的資料為使用者充分渲染網頁。但是,我們的Python程式沒有返回並向伺服器請求多個檔案的邏輯,它只能讀取我們已經請求的單個HTML檔案。
1、初識urllib庫
urllib是標準庫,在 Python 3.x 裡,urllib2 改名為 urllib,被分成一些子模組:urllib.request 、urllib.parse和urllib.error。
urlopen 用來開啟並讀取一個從網路擷取的遠程對象。
匯入urlopen ,然後調用 html.read() 擷取網頁的HTML內容。
>>> from urllib.request import urlopen>>> html = urlopen("http://pythonscraping.com/pages/page1.html")>>> print(html.read())b'<html>\n<head>\n<title>A Useful Page</title>\n</head>\n<body>\n<h1>An Interesting Title</h1>\n<div>\nLorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n</div>\n</body>\n</html>\n'
2、使用虛擬環境
可以用虛擬環境儲存庫檔案。
如下:建立了一個叫作scrapingEnv的新環境,然後啟用它;在建立的scrapingEnv環境裡,可以安裝並使用BeautifulSoup;最後通過釋放命令來退出環境。
$ virtualenv scrapingEnv$ cd scrapingEnv/$ source bin/activate(scrapingEnv)ryan$ pip install beautifulsoup4(scrapingEnv)ryan$ python> from bs4 import BeautifulSoup>(scrapingEnv)ryan$ deactivate$
可以使用如下任意一命令安裝BeautifulSoup庫
pip3 install bs4pip3 install beautifulsoup4
3、初識BeautifulSoup庫
把HTML內容傳到BeautifulSoup對象(html.parser是內建的解析器),從網頁中提取的 <h1> 標籤被嵌在 BeautifulSoup 對象 bsObj 結構的第二層(html → body → h1)
>>> from urllib.request import urlopen>>> from bs4 import BeautifulSoup>>> html = urlopen("http://pythonscraping.com/pages/page1.html")>>> bsObj = BeautifulSoup(html.read(), 'html.parser')>>> print(bsObj.h1)<h1>An Interesting Title</h1>
*下面的所有函數調用都可以產生同樣的結果:
bsObj.h1
bsObj.html.body.h1
bsObj.body.h1
bsObj.html.h1
4、處理異常
網頁在伺服器上不存在(或者擷取頁面的時候出現錯誤), urlopen函數會拋出“HTTPError”異常。
如果伺服器不存在(就是說連結打不開,或者是URL連結寫錯了),urlopen會返回一個None對象。
用以下方式處理:
try: html = urlopen("http://pythonscraping.com/pages/page1.html")except HTTPError as e: print(e) # 中斷程式,或者執行另一個方案else: if html is None: print("URL is not found") else: # 程式繼續 pass
調用BeautifulSoup對象裡的一個標籤不存在會返回None對象。
再調用這個None對象下面的子標籤,就會發生 AttributeError錯誤。
用以下方式處理:
try: bsObj = BeautifulSoup(html.read(), 'html.parser') badContent = bsObj.body.h2except AttributeError as e: print("Tag was not found")else: if badContent == None: print("Tag was not found") else: print(badContent)
5、重新整理組織以上代碼
# -*- coding: utf-8 -*-from urllib.request import urlopenfrom urllib.error import HTTPErrorfrom bs4 import BeautifulSoupdef getTitle(url): try: html = urlopen(url) except HTTPError as e: return None try: bsObj = BeautifulSoup(html.read(), 'html.parser') title = bsObj.body.h1 except AttributeError as e: return None return title title = getTitle("http://pythonscraping.com/pages/page1.html")if title == None: print("Title could not be found")else: print(title)
我們建立了一個getTitle函數,用於返回網頁的標題。如果擷取網頁的時候遇到問題就返回一個None對象。
在getTitle函數裡面,我們像前面那樣檢查了HTTPError ,然後把兩行BeautifulSoup代碼封裝在一個try語句裡面。這兩行中的任何一行有問題,AttributeError都可能被拋出(如果伺服器不存在, html 就是一個None對象,html.read() 就會拋出 AttributeError )。
《Python網路資料擷取》讀書筆記(一)