《Python網絡爬蟲權威指南》讀書筆記1(第1章:初見爬蟲)


前言

這本書的所有代碼示例都在GitHub網站上(https://github.com/REMitchell/python-scraping),可以查看和下載。

如果想要更全面地學習Python,Bill Lubanovic寫的《Python語言及其應用》是一本非常好的教材。(筆者還沒有看,筆者選用的入門教材是《Python編程:從入門到實踐》)

補充材料(代碼示例、練習等)可以從https://github.com/REMitchell/python-scraping下載。

第1章 初見網絡爬蟲

1.1 網絡連接

from urllib.request import urlopen

html = urlopen('http://pythonscraping.com/pages/page1.html')
print(html.read())

把上面這段代碼保存為scrapetest.py,然后再終端運行如下指令:

 python scrapetest.py

這會輸出http://pythonscraping.com/pages/page1.html 這個網頁的全部HTML代碼。更准確地說,這會輸出在域名為http://pythonscraping.com 的服務器上<網絡應用根地址>/pages 文件夾里的HTML文件pages.html 的源代碼。

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'

urllib是Python的標准庫,建議讀讀這個庫的Python文檔

1.2 BeautifulSoup

1.2.1 安裝BeautifulSoup

在Windows系統上安裝:

1、從下載頁面下載最新的BeautifulSoup(網址為:http://www.crummy.com/software/BeautifulSoup/

2、解壓到python文件夾下,並切換到...python/beautifulsoup4-4.1.3/目錄下

3、執行:python setup.py install

4、在python終端里導入測試

筆者出現了“ cannot import name 'HTMLParseError'”錯誤

經過搜索,解決方法如下:

先卸載掉之前安裝的bs4,再用pip命令重新安裝。

PS D:\Program Files\python-3.7.4-amd64> pip3 uninstall beautifulsoup4
Uninstalling beautifulsoup4-4.8.0:
  Would remove:
    d:\program files\python-3.7.4-amd64\lib\site-packages\beautifulsoup4-4.8.0-py3.7.egg
Proceed (y/n)? y
  Successfully uninstalled beautifulsoup4-4.8.0
PS D:\Program Files\python-3.7.4-amd64> pip install beautifulsoup4
Collecting beautifulsoup4
  Downloading https://files.pythonhosted.org/packages/1a/b7/34eec2fe5a49718944e215fde81288eec1fa04638aa3fb57c1c6cd0f98c3/beautifulsoup4-4.8.0-py3-none-any.whl (97kB)
    100% |████████████████████████████████| 102kB 137kB/s
Requirement already satisfied: soupsieve>=1.2 in d:\program files\python-3.7.4-amd64\lib\site-packages\soupsieve-1.9.2-py3.7.egg (from beautifulsoup4) (1.9.2)
Installing collected packages: beautifulsoup4
Successfully installed beautifulsoup4-4.8.0

然后,就成功啦。

 1.2.2 運行BeautifulSoup

把本章開頭的例子重新再運行看看:

from urllib.request import urlopen
from bs4 import BeautifulSoup

html = urlopen('http://pythonscraping.com/pages/page1.html')
bs = BeautifulSoup(html.read(),'html.parser')
print(bs.h1)

輸出結果是:

<h1>An Interesting Title</h1>

html.read()獲取網頁的HTML內容。除了文本字符串,BeautifulSoup還可以使用urlopen直接返回的文件對象,而不需要先調用.read()函數:bs = BeautifulSoup(html.read(),'html.parser')

下面的所有函數調用都可以產生相同的結果:

bs.html.body.h1

bs.body.h1

bs.html.h1

當你創建一個BeautifulSoup對象時,需要傳入兩個參數:第一個參數是該對象所基於的HTML文本,第二個參數指定了你希望BeautifulSoup用來創建該對象的解析器。

html.parser是python3中的一個解析器,不需要單獨安裝。

另一個常用的解析器是lxml,可以通過pip命令安裝:pip install lxml

BeautifulSoup使用lxml解析器時,只需要改變解析器參數:bs = BeautifulSoup(html.read(),'lxml')

和html.parser相比,lxml的優點在於解析“雜亂”或者包含錯誤語法的HTML代碼的性能更優一些。lxml的一個缺點是它必須單獨安裝,並且依賴於第三方C語言庫。相對於html.parser來說,這可能會導致可移植性和易用性問題。

另一個常用的HTML解析器是html5lib。和lxml一樣,html5lib也是一個具有容錯性的解析器。它也以來於外部依賴,並且比lxml和html.parser都慢。

1.2.3 可靠的網絡連接以及異常處理

html = urlopen('http://pythonscraping.com/pages/page1.html')

這行代碼主要會發生兩種異常:

  • 網頁在服務器上不存在(或者獲取頁面的時候出現錯誤)
  • 服務器不存在

發生第一種異常時,程序會返回HTTP錯誤。urlopen函數會拋出HTTPError異常。用下面的方式處理這種異常:

from urllib.error import HTTPError
from urllib.request import urlopen
from bs4 import BeautifulSoup

try:
    html = urlopen('http://pythonscraping.com/pages1/page1.html')
except HTTPError as e:
    print(e)
    # 返回空值,中斷程序,或者執行另一個方案
else:
    # 程序繼續。注意:如果你已經在上面異常捕捉那一段代碼里返回或者終端(break),
    # 那么就不需要使用else語句了,這段代碼也不會執行
    bs = BeautifulSoup(html.read(),'html.parser')
    print(bs.h1)

筆者故意將網址寫錯了,得到下面的結果:

HTTP Error 404: Not Found

如果服務器不存在,urlopen會拋出一個URLError異常。這就意味着獲取不到服務器,並且由遠程服務器負責返回HTTP狀態碼,所以不能拋出HTTPError異常,而且還應該捕獲到更嚴重的URLError異常。增加以下檢查代碼:

from urllib.error import HTTPError
from urllib.request import urlopen
from urllib.error import URLError
from bs4 import BeautifulSoup

try:
    html = urlopen('http://pythonscrapingthisurldoesnotfound.com/pages1/page1.html')
except HTTPError as e:
    print(e)
except URLError as e:
    print('The server could not be found!')
else:
    bs = BeautifulSoup(html.read(),'html.parser')
    print(bs.h1)
The server could not be found!

當你調用BeautifulSoup對象里的一個標簽時,增加一個檢查條件以保證標簽確實存在。如果你想調用的標簽不存在,BeautifulSoup就會返回None對象。不過,如果調用這個None對象下面的子標簽,就會發生AttributerError錯誤。

下面這行代碼(nonExistenTag是虛擬標簽,BeautifulSoup對象里實際沒有)

print(bs.nonExistenTag)

會返回一個None對象。

None
UserWarning: .nonExistenTag is deprecated, use .find("nonExisten") instead. If you really were looking for a tag called nonExistenTag, use .find("nonExistenTag")
  name=tag_name

處理這個對象是十分必要的。如果你不檢查,直接調用這個None對象的子標簽,就會很麻煩,如下所示。

 print(bs.nonExistenTag.someTag)

這時就會返回一個異常:

AttributeError: 'NoneType' object has no attribute 'someTag'

為了避免這兩種情況,最簡單的方式就是對兩種情形進行檢查:

 try:
        badContent = bs.nonExistingTag.anotherTag
    except AttributeError as e:
        print('Tag was not found')
    else:
        if badContent == None:
            print('Tag was not found')
        else:
            print(badContent)

重新組織一下代碼,讓它不那么難寫難讀:

from urllib.error import HTTPError
from urllib.request import urlopen
from urllib.error import URLError
from bs4 import BeautifulSoup

def getTitle(url):
    try:
        html = urlopen(url)
    except HTTPError as e:
        return None
    except URLError as e: return None try:
        bs = BeautifulSoup(html.read(),'html.parser')
        title = bs.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 found')
else:
    print(title)

 

創建了一個getTitle函數,它可以返回網頁的標題,如果獲取網頁的時候遇到問題就會返回一個None對象。在getTitle函數里面,我們像前面那樣檢查了HTTPError,黃色標記的是我覺得書上漏掉的,檢查URLError錯誤。然后把兩行BeautifulSoup代碼封裝在一個try語句里。這兩行有任意一行有問題都會拋出AttributeError。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM