1. 程式人生 > >《Python網絡數據采集》讀書筆記(一)

《Python網絡數據采集》讀書筆記(一)

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 bs4
pip3 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.h2
except 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 urlopen
from urllib.error import HTTPError
from bs4 import BeautifulSoup


def 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網絡數據采集》讀書筆記(一)