天天看點

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

點選檢視第一章 點選檢視第三章

第2章

編寫第一個網絡爬蟲

筆者是一個喜歡學習的人,自學了各方面的知識,總結發現:學習的動力來自于興趣,興趣則來自于動手做出成果的快樂。是以,筆者特意将動手的樂趣提前。在第2章,讀者就可以體會到通過完成一個簡單的Python網絡爬蟲而帶來的樂趣。希望這份喜悅能讓你繼續學習本書的其他内容。

本章主要介紹如何安裝Python和編輯器Jupyter、Python的一些基礎文法以及編寫一個最簡單的Python網絡爬蟲。

2.1 搭建Python平台

Python是一種計算機程式語言,由于其簡潔性、易學性和可擴充性,已成為最受歡迎的程式語言之一。在2016年最受歡迎的程式設計語言中,Python已經超過C++排名第3位。另外,由于Python擁有強大而豐富的庫,是以可以用來處理各種工作。

在網絡爬蟲領域,由于Python簡單易學,又有豐富的庫可以很好地完成工作,是以很多人選擇Python進行網絡爬蟲。

2.1.1 Python的安裝

Python的安裝主要有兩種方式:一是直接下載下傳Python安裝包安裝,二是使用Anaconda科學計算環境下載下傳Python。

根據筆者的經驗,這兩種方式也對應着用Python來爬蟲的兩類人群:如果你希望成為Python開發人員或者爬蟲工程師,筆者推薦你直接下載下傳Python安裝包,配合着Pycharm編輯器,這将提升你的開發效率;如果你希望成為資料分析師或者商業分析師,爬蟲隻是友善之後做資料分析,筆者推薦你使用Anaconda,配合着自帶的Jupyter Notebook,這會提升你的分析效率。

由于網絡爬蟲需要較多的代碼調試,是以我推薦初學者使用Anaconda。因為Anaconda除了包含了Python安裝包,還提供了衆多科學計算的第三方庫,如Numpy、Scipy、Pandas和Matplotlib等,以及機器學習庫,如Scikit-Learn等。而且它并不妨礙你之後使用Pycharm開發。

請讀者選擇一種下載下傳,不要兩種都用,不然會帶來Python版本管理的混亂。

第一種方法:Anaconda的安裝十分簡單,隻需兩步即可完成。下面将介紹在Windows下安裝Anaconda的步驟,在Mac下的安裝方法與此類似。

步驟一:下載下傳Anaconda。打開Anaconda官方網站下載下傳頁面

https://www.anaconda.

com/download/,下載下傳最新版的Anaconda。如果在國内通路,推薦使用清華大學的鏡像

https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/

。如圖2-1所示。

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

步驟二:安裝Anaconda。輕按兩下打開Anaconda安裝檔案,就像安裝普通軟體一樣,直接單擊Install安裝即可。注意,在圖2-2所示的對話框中勾選第一個和第二個複選框。按照提示操作後,安裝即可。

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

第二種方法:使用Python安裝包方法也非常簡單。下面将介紹在Windows下安裝的步驟,在Mac下的安裝方法類似。

步驟一:下載下傳Python。打開Python下載下傳頁面

https://www.python.org/downloads/

,下載下傳最新版的Python,如圖2-3所示。

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

步驟二:安裝Python。輕按兩下打開Python安裝檔案,選擇 Add Python 3.7 to PATH,之後單擊InstallNow安裝即可。

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

2.1.2 使用pip安裝第三方庫

pip是Python安裝各種第三方庫(package)的工具。

對于第三方庫不太了解的讀者,可以将庫了解為供使用者調用的代碼組合。在安裝某個庫之後,可以直接調用其中的功能,使得我們不用自己寫代碼也能實作某個功能。這就像你為計算機殺毒時,會選擇下載下傳一個防毒軟體,而不是自己寫一個防毒軟體,直接使用防毒軟體中的殺毒功能來殺毒就可以了。這個比方中的防毒軟體就像是第三方庫,殺毒功能就是第三方庫中可以實作的功能,你可以調用第三方庫實作某個功能。

由于Anaconda或者Python安裝包自帶了pip,是以不用再安裝pip。

在下面的例子中,我們将介紹如何用pip安裝第三方庫bs4,它可以使用其中的BeautifulSoup解析網頁。

步驟一:打開cmd.exe,在Windows中為cmd,在Mac中為terminal。在Windows中,cmd是指令提示符,輸入一些指令後,cmd.exe可以執行對系統的管理。單擊“開始”按鈕,在“搜尋程式和檔案”文本框中輸入cmd後按Enter鍵,系統會打開指令提示符視窗,如圖2-5所示。在Mac中,可以直接在“應用程式”中打開terminal程式。

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

步驟二:安裝bs4的Python庫。在cmd中鍵入pip install bs4後按Enter鍵,如果出現successfully installed,就表示安裝成功,如圖2-6所示。

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

除了bs4這個庫,之後還會用到requests庫、lxml庫等其他第三方庫,幫助我們更好地進行網絡爬蟲。正因為這些第三方庫的存在,才使得Python在爬蟲領域越來越友善、越來越活躍。

2.1.3 使用編輯器Jupyter 程式設計

如果你使用Anaconda安裝的Python,那麼可以使用Anaconda自帶的Jupyter Notebook程式設計;如果你使用Python安裝包下載下傳的Python,下一節會介紹Pycharm的安裝方法。為了友善大家學習和調試代碼,本書推薦使用Anaconda自帶的Jupyter Notebook。下面将介紹Jupyter Notebook的使用方法。

步驟一:通過cmd打開Jupyter。打開cmd,鍵入jupyter notebook後按Enter鍵,浏覽器啟動Jupyter界面,位址預設為

http://localhost:8888/tree

,如圖2-7所示。

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

步驟二:建立Python檔案。這時浏覽器會開啟一個頁面,在頁面中選擇想建立檔案的檔案夾,單擊右上角的New按鈕,從下拉清單中選擇Python 3作為希望啟動的Notebook類型,如圖2-8所示。

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

步驟三:在新建立的檔案中編寫Python程式。鍵入print('hello world!')後,可以按Shift + Enter快捷鍵執行剛剛的代碼,結果如圖2-9所示。

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

為什麼本書使用Jupyter Notebook學習和編寫Python腳本呢?

首先,Jupyter Notebook的互動式程式設計可以分段運作Python,對于網絡爬蟲這種分階段(擷取網頁-解析網頁-存儲資料)運作的腳本來說,在寫代碼和測試階段可以邊看邊寫,可以加快調試代碼的速度,非常适合debug(代碼糾錯)。

其次是展示,Jupyter Notebook能夠把運作和輸出的結果儲存下來,下次打開這個Notebook時也可以看到之前運作的結果。除了可以編寫代碼外,Jupyter還可以添加各種元素,比如圖檔、視訊、連結等,同時還支援Markdown。

在完成代碼之後,還可以在Jupyter左上角點選File > Download as > Python,下載下傳為.py檔案,就可以放到其他編輯器裡運作了。

如果你對Python的其他自定義功能有要求的話,推薦下載下傳Jupyter的插件nbextensions。具體指引可以到筆者知乎或本書官網www.santostang.com 了解。

2.1.4 使用編輯器Pycharm程式設計

如果你使用Python安裝包下載下傳的Python,推薦選擇Pycharm編輯器。

步驟一:下載下傳Pycharm。打開Pycharm下載下傳頁面

https://www.jetbrains.com/

pycharm/download ,下載下傳Community版本,如圖2-10所示。

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

步驟二:安裝Pycharm。輕按兩下打開Pycharm安裝檔案,根據自己電腦選擇32bit還是64bit,記得在Create Associations勾選 .py,安裝即可,如圖2-11所示。

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

步驟三:打開Pycharm。在開始頁面,選擇自己喜歡的主題,如圖2-12所示。

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

步驟三:随後點選Create New Project建立一個新的項目,如圖2-13所示。

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

步驟三: 選擇好存儲項目的位置,這裡我給項目起的名稱是“WebScraping”,你可以按照自己的需求存放項目位址,如圖2-14所示。

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

步驟三:進入Pycharm頁面後,會看到如下頁面。這時,點選File > New > Python File,并填上python檔案名,例如“test”。建立完test.py檔案後,打開test.py,鍵入print('hello world!')。選中代碼,右鍵選擇 Run ‘test’,即可得到結果,如圖2-15所示。

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

2.2 Python 使用入門

本節主要介紹Python的一些基礎文法。如果你已經學會使用Python,可以跳過這一節,直接開始編寫第一個Python網絡爬蟲。

2.2.1 基本指令

Python是一種非常簡單的語言,最簡單的就是print,使用print可以列印出一系列結果。例如,鍵入print("Hello World!"),列印的結果如下(同圖2-9):

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

Hello World!

另外,Python要求嚴格的代碼縮進,以Tab鍵或者4個空格進行縮進,代碼要按照結構嚴格縮進,例如:

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

如果需要注釋某行代碼,那麼可以在代碼前面加上“#”,例如:

In [3]:# 在前面加上#,代表注釋

print ("Hello World!")

2.2.2 資料類型

Python是面向對象(object oriented)的一種語言,并不需要在使用之前聲明需要使用的變量和類别。下面将介紹Python的4種資料類型。

1. 字元串(string)

字元串是常見的資料類型,一般用來存儲類似“句子”的資料,并放在單引号(')或雙引号(")中。如果要連接配接字元串,那麼可以簡單地加起來。

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

Python Web Scraping by Santos

如果字元串包含單引号(')和雙引号("),應該怎麼辦?可以在前面加上右斜杠(),例如以下案例:

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

I'm Santos. I love "python".

2. 數字(Number)

數字用來存儲數值,包含兩種常用的數字類型:整數(int)和浮點數(float),其中浮點數由整數和小數部分組成。兩種類型之間可以互相轉換,如果要将整數轉換為浮點數,就在變量前加上float;如果要将浮點數轉換為整數,就在變量前加上int,例如:

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

7

還有其他兩種複雜的資料類型,即長整數和複數,由于不常用到,感興趣的讀者可以自己學習。

3. 清單(list)

如果需要把上述字元串和數字囊括起來,就可以使用清單。清單能夠包含任意種類的資料類型和任意數量。建立清單非常容易,隻要把不同的變量放入方括号中,并用逗号分隔即可,例如:

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

怎麼通路清單中的值呢?可以在方括号中标明相應的位置索引進行通路,與一般認知不一樣的是,索引從0開始,例如:

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

list1[0]: Python

list2[1:3]: [2, 3]

如何修改清單中的值呢?可以直接為清單中的相應位置賦予一個新值,例如:

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

['Python', 'new', 'Scrappy']

如果想要給清單添加值呢?可以用append()方法,例如:

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

['Python', 'new', 'Scrappy', 'by Santos']

4. 字典(Dictionaries)

字典是一種可變容器模型,正如其名,字典含有“字”(直譯為鍵值,key)和值(value),使用字典就像是自己建立一個字典和查字典的過程。每個存儲的值都對應着一個鍵值key,key必須唯一,但是值不需要唯一。值也可以取任何資料類型,例如:

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

Alex

{'Name': 'Alex', 'Age': 7, 'Class': 'First'}

如何周遊通路字典中的每一個值呢?這裡需要用到字典和循環的結合,例如:

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

Name Alex

Age 7

Class First

如果想修改字典中的值或者加入新的鍵值呢?可以直接修改和加入,例如:

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

{'Name': 'Tom', 'Age': 7, 'Class': 'First', 'Gender':'M'}

2.2.3 條件語句和循環語句

條件語句可以使得當滿足條件的時候才執行某部分代碼。條件為布爾值,也就是隻有True和False兩個值。當if判斷條件成立時才執行後面的語句;當條件不成立的時候,執行else後面的語句,例如:

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章
帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

You are studying python.

如果需要判斷的有多種條件,就需要用到elif,例如:

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

You are studying java.

Python的條件語句注意不要少了冒号(:)。

循環語句能讓我們執行一個代碼片段多次,循環分為for循環和while循環。

for循環能在一個給定的順序下重複執行,例如:

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

Beijing

Shanghai

Guangzhou

除了對清單進行直接循環,有時我們還會使用range()進行循環,首先用len(citylist)得到清單的長度為3,然後range(3)會輸出清單[0,1,2],進而實作循環,得到和上面一樣的結果。例如:

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

while循環能不斷重複執行,隻要能滿足一定條件,例如:

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

1

2

2.2.4 函數

在代碼很少的時候,我們按照邏輯寫完就能夠很好地運作。但是如果代碼變得龐大複雜起來,就需要自己定義一些函數(Functions),把代碼切分成一個個方塊,使得代碼易讀,可以重複使用,并且容易調整順序。

其實Python就自帶了很多函數,例如下面的sum()和abs()函數,我們可以直接調用。

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

10

此外,我們也可以自己定義函數。一個函數包括輸入參數和輸出參數,Python的函數功能可以用y = x +1的數學函數來了解,在輸入x=2的參數時,y輸出3。但是在實際情況中,某些函數輸入和輸出參數可以不用指明。下面定義一個函數:

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

3

參數必須要正确地寫入函數中,函數的參數也可以為多個,也可以是不同的資料類型,例如可以是兩個參數,分别是字元串和清單型的。

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

apple banana orange

2.2.5 面向對象程式設計

在介紹面向對象程式設計之前先說明面向過程程式設計。面向過程程式設計的意思是根據業務邏輯從上到下寫代碼,這個容易被初學者接受,按照邏輯需要用到哪段代碼寫下來即可。

随着時間的推移,在程式設計的方式上又發展出了函數式程式設計,把某些功能封裝到函數中,需要用時可以直接調用,不用重複撰寫。這也是上面提到的函數式程式設計,函數式的程式設計方法好處是節省了大量時間。

接下來,又出現了面向對象程式設計。面向對象程式設計是把函數進行分類和封裝後放入對象中,使得開發更快、更強。例如:

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

santos

18

看到這裡,也許你有疑問,要實作上述代碼的結果,使用函數式程式設計不是比面向對象程式設計更簡單嗎?例如,如果我們使用函數式程式設計,可以寫成:

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

此處确實是函數式程式設計更容易。使用函數式程式設計,我們隻需要寫清楚輸入和輸出變量并執行函數即可;而使用面向對象的程式設計方法,首先要建立封裝對象,然後還要通過對象調用被封裝的内容,豈不是很麻煩?

但是,在某些應用場景下,面向對象程式設計能夠顯示出更大的優勢。

如何選擇函數式程式設計和面向對象程式設計呢?可以這樣進行選擇,如果各個函數之間獨立且無共用的資料,就選用函數式程式設計;如果各個函數之間有一定的關聯性,那麼選用面向對象程式設計比較好。

下面簡單介紹面向對象的兩大特性:封裝和繼承。

1. 封裝

封裝,顧名思義就是把内容封裝好,再調用封裝好的内容。封裝分為兩步:

第一步為封裝内容。

第二步為調用被封裝的内容。

(1)封裝内容

下面為封裝内容的示例。

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

self在這裡隻是一個形式參數,當執行obj1 = Person('santos', 18 )時,self等于obj1,此處将santos和18分别封裝到obj1及self的name和age屬性中。結果是obj1有name和age屬性,其中name="santos",age=18。

(2)調用被封裝的内容

調用被封裝的内容時有兩種方式:通過對象直接調用和通過self間接調用。

通過對象直接調用obj1對象的name和age屬性,代碼如下:

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

通過self間接調用時,Python預設會将obj1傳給self參數,即obj1.detail(obj1)。此時方法内部的self = obj1,即self.name='santos',self.age =18,代碼如下:

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

上述例子定義了一個Person的類。在這個類中,可以通過各種函數定義Person的各種行為和特性,要讓代碼顯得更加清晰有效,就要在調用Person類各種行為的時候也可以随時提取。這比僅使用函數式程式設計更加友善。

面對對象的程式設計方法不會像平時按照執行流程去思考,在這個例子中,是把Person這個類型視為一個對象,它擁有name和age兩個屬性,在調用過程中,讓自己把自己列印出來。

綜上所述,對于面向對象的封裝來說,其實就是使用構造方法将内容封裝到對象中,然後通過對象直接或self間接擷取被封裝的内容。

2. 繼承

繼承是以普通的類為基礎建立專門的類對象。面向對象程式設計的繼承和現實中的繼承類似,子繼承了父的某些特性,例如:

貓可以:喵喵叫、吃、喝、拉、撒

狗可以:汪汪叫、吃、喝、拉、撒

如果我們要分别為貓和狗建立一個類,就需要為貓和狗實作他們所有的功能,代碼如下,這裡為僞代碼,無法在python執行:

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

從上述代碼不難看出,吃、喝、拉、撒是貓狗共同的特性,我們沒有必要在代碼中重複編寫。如果用繼承的思想,就可以寫成:

動物:吃喝拉撒

貓:喵喵叫(貓繼承動物的功能)

狗:汪汪叫(狗繼承動物的功能)

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章
帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

小白家的小黑貓 吃

喵喵叫

胖子家的小瘦狗 吃

汪汪叫

對于繼承來說,其實就是将多個類共有的方法提取到父類中,子類繼承父類中的方法即可,不必一一實作每個方法。

2.2.6 錯誤處理

在程式設計過程中,我們不免會遇到寫出來的程式運作錯誤,是以程式員經常戲稱自己是在“寫bug(錯誤)而非寫程式”。這些錯誤一般來說會使得整個程式停止運作,但是在Python中,我們可以用try/except語句來捕獲異常。

try/except使用try來檢測語句塊中的錯誤,如果有錯誤的話,except則會執行捕獲異常資訊并處理。以下是一個執行個體:

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

division by zero

上述代碼首先執行try裡面的語句,除以0産生運算錯誤後,會執行except裡的語句,将錯誤列印出來。在網絡爬蟲中,它可以幫我們處理一些無法擷取到資料報錯的情況。

此外,如果我們并不想列印錯誤,就可以用pass空語句。

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

2.3 編寫第一個簡單的爬蟲

當了解了Python的基礎文法後,就算你是程式設計小白,也可以輕松爬取一些網站了。

為了友善大家練習Python網絡爬蟲,筆者專門搭建了一個部落格網站用于爬蟲的教學,本書教學部分的爬蟲全部基于爬取筆者的個人部落格網站(www.santostang.com )。一方面,由于這個網站的設計和架構不會更改,是以本書的網絡爬蟲代碼可以一直使用;另一方面,由于這個網站由筆者擁有,是以避免了一些法律上的風險。

下面以爬取筆者的個人部落格網站為例擷取第一篇文章的标題名稱,教大家學會一個簡單的爬蟲。

2.3.1 第一步:擷取頁面

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章
帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

上述代碼就能擷取部落格首頁的HTML代碼,HTML是用來描述網頁的一種語言,也就是說網頁呈現的内容背後都是HTML代碼。如果你對HTML不熟悉的話,可以先去w3school (

http://www.w3school.com.cn/html/index.asp

) 學習一下,大概花上幾個小時就可以了解HTML。

在上述代碼中,首先import requests引入包requests,之後擷取網頁。

(1)首先定義link為目标網頁位址。

(2)之後用headers來定義請求頭的浏覽器代理,進行僞裝。

(3)r是requests的Response回複對象,我們從中可以擷取想要的資訊。r.text是擷取的網頁内容代碼。

運作上述代碼得到的結果如圖2-16所示。

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

2.3.2 第二步:提取需要的資料

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章
帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

在擷取整個頁面的HTML代碼後,我們需要從整個網頁中提取第一篇文章的标題。

這裡用到BeautifulSoup這個庫對頁面進行解析,BeautifulSoup将會在第4章進行詳細講解。首先需要導入這個庫,然後把HTML代碼轉化為soup對象,接下來用soup.find("h1", class_="post-title").a.text.strip()得到第一篇文章的标題,并且列印出來。

soup.find("h1", class_="post-title").a.text.strip()的意思是,找到第一篇文章标題,定位到class是"post-title"的h1元素,提取a元素,提取a元素裡面的字元串,strip()去除左右空格。

對初學者來說,使用BeautifulSoup從網頁中提取需要的資料更加簡單易用。

那麼,我們怎麼從那麼長的代碼中準确找到标題的位置呢?

這裡就要隆重介紹Chrome浏覽器的“檢查(審查元素)”功能了。下面介紹找到需要元素的步驟。

步驟一:使用Chrome浏覽器打開部落格首頁www.santostang.com 。右擊網頁頁面,在彈出的快捷菜單中單擊“檢查”指令,如圖2-17所示。

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

步驟二:出現如圖2-18所示的審查元素頁面。單擊左上角的滑鼠鍵按鈕,然後在頁面上單擊想要的資料,下面的Elements會出現相應的code所在的地方,就定位到想要的元素了。

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

步驟三:在代碼中找到标藍色的地方,為

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

學習筆記(2) – 同一頁面多圖表。我們可以用soup.find("h1", class_="post-title").a.text.strip()提取該博文的标題。

2.3.3 第三步:存儲資料

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

存儲到本地的txt檔案非常簡單,在第二步的基礎上加上2行代碼就可以把這個字元串儲存在text中,并存儲到本地。txt檔案位址應該和你的Python檔案放在同一個檔案夾。

傳回檔案夾,打開title.txt檔案,其中的内容如圖2-19所示。

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

2.4 Python實踐:基礎鞏固

學習完基礎知識,做完第一個爬蟲例子後,是不是覺得網絡爬蟲并沒有想象中那麼難呢?本書的目标就是希望你可以快速上手Python和爬蟲,然後在後面的實戰中學習。但是Python爬蟲入門簡單,一步步深入學習後,你會發現坑越來越多。隻有認真閱讀、反複練習,才能熟能生巧。

為了鞏固大家學習Python網絡爬蟲的成果,第2章~第7章的結尾都提供了一個實踐項目。這些實踐的目的一是讓讀者從實踐中檢驗自己學習了多少知識,二是進一步鞏固在該章節中學習的知識。這些實踐項目的完整代碼都在書中,你也可以從本書配書資源的下載下傳位址下載下傳。除此之外,章末還提供了一個進階問題供感興趣的讀者思考。

如果你是一個程式設計新手,在進一步學習Python程式設計之前需要記得以下3點:

(1)實踐是最快的學習方式。如果你打算通過閱讀本書而學會Python爬蟲,就算讀上100遍可能也不會達到很好的效果,最有效的方法就是:手輸代碼,反複練習。這也是為什麼本書均通過項目案例來講解Python網絡爬蟲的原因。

(2)搜尋引擎是最好的老師。如果遇到不明白的問題,請學會使用百度或谷歌引擎搜尋。就筆者自己的體驗而言,谷歌的有效資訊檢索速度比百度快,較新的回答很有可能是英文的,但是如果你的英文閱讀能力不行,就另當别論了。記得使用谷歌搜尋時,找到Stack Overflow網站上的回答可以非常快地解決你的問題。

(3)請不要複制、粘貼代碼。複制、粘貼代碼除了可以讓你在短時間内完成任務之外,沒有任何好處。隻有通過親自輸入代碼,并不斷重複、不斷加快速度,才會提升你的程式設計能力和程式設計效率。否則給你一張白紙,你會什麼代碼都寫不出。

本章實踐的項目主要是幫助Python的初學者鞏固之前學過的知識,如果你已經對Python有所了解,可以跳過以下部分。為了達到最好的效果,請先自行完成下面的題目。每一題後面都會提供答案,這些答案并不是唯一解,也不是讓你不思考直接複制、粘貼運作的,而是用來對比思路,鞏固Python基礎内容的。

2.4.1 Python基礎試題

試題1:請使用Python中的循環列印輸出從1到100的所有奇數。

試題2:請将字元串“你好$$$我正在學Python@#@#現在需要&&&修改字元串”中的符号變成一個空格,需要輸出的格式為:“你好 我正在學Python 現在需要 修改字元串”。

試題3:輸出9×9乘法口訣表。

試題4:請寫出一個函數,當輸入函數變量月利潤為I時,能傳回應發放獎金的總數。例如,輸出“利潤為100 000元時,應發放獎金總數為10 000元”。

其中,企業發放的獎金根據利潤提成。利潤(I)低于或等于10萬元時,獎金可提10%;利潤高于10萬元,低于20萬元時,低于10萬元的部分按10%提成,高于10萬元的部分,可提成7.5%;利潤在20萬元到40萬元之間時,高于20萬元的部分可提成5%;利潤在40萬元到60萬元之間時,高于40萬元的部分可提成3%;利潤在60萬元到100萬元之間時,高于60萬元的部分可提成1.5%;利潤高于100萬元時,超過100萬元的部分按1%提成。

試題5:用字典的值對字典進行排序,将{1: 2, 3: 4, 4:3, 2:1, 0:0}按照字典的值從大到小進行排序。

試題6:請問以下兩段代碼的輸出分别是什麼?

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章
帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

試題7:請問以下兩段代碼的輸出分别是什麼?

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章
帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

2.4.2 參考答案

試題1答案:

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

在上述代碼中,range(1,101) 傳回的是從1到100所有整數的清單list,然後使用循環判斷這個數字除以2的餘數是否為1,i % 2傳回的是i除以2的餘數。如果餘數等于1,就輸出該數字。

試題2答案:

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

在上述代碼中,使用replace方法可以将字元串中的一些字元替換成想要的字元。例如,str1.replace('$$$', ' ')就是把str1中的'$$$'替換成空格。

其實還可以采用另一種更加簡單的方法:

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

這裡用到一個庫re(正規表達式),使用其中的re.sub可以進行替換。正規表達式的功能将在第5章進行詳細說明。

試題3答案:

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

運作上述代碼,得到的結果如圖2-20所示。

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

上述代碼使用了兩個循環的嵌套,在第一個循環中i為1,在第二個循環中j為1。當j完成循環後,i會加1,變成2,j又從1開始一個新的循環,進而得到輸出的這個9×9乘法表。

試題4答案:

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章
帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

在上述代碼中,計算應發獎金時,我們對不同的情況使用if和elif進行了不同的處理。

還可以使用一個比較簡潔的方式:

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

試題5答案:

帶你讀《Python網絡爬蟲從入門到實踐(第2版)》之二:編寫第一個網絡爬蟲第2章

運作上述代碼,輸出的結果是:

[(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)]

對字典進行排序是不可能的,隻有把字典轉換成另一種方式才能排序。字典本身是無序的,但是如清單元組等其他類型是有序的,是以需要用一個元組清單來表示排序的字典。

試題6答案:

第一段代碼輸出的結果是:1

第二段代碼輸出的結果是:[1]

從結果發現,在第一段代碼中,a為數字int,函數改變不了函數以外a的值,輸出結果仍然為1;而在第二段代碼中,a為清單,函數将函數以外的a值改變了。

這是因為在Python中對象有兩種,即可更改(mutable)與不可更改(immutable)對象。在Python中,strings字元串、tuples元組和numbers數字是不可更改對象,而list清單、dict字典等是可更改對象。

在第一段代碼中,當一個引用傳遞給函數時,函數自動複制一份引用。函數裡和函數外的引用是不一樣的。

在第二段代碼中,函數内的引用指向的是可變對象清單a,函數内的清單a和函數外的清單a是同一個。

試題7答案:

第一段代碼輸出的結果是:bbb aaa aaa

第二段代碼輸出的結果是:[1] [1] [1]

代碼中的p1.name="bbb"表示執行個體調用了類變量,其實就是函數傳參的問題。p1.name一開始指向類變量name="aaa",但是在執行個體的作用域裡把類變量的引用改變了,就變成了一個執行個體變量,self.name不再引用Person的類變量name了,是以第一個答案是bbb。而後面的兩個答案還是調用類變量name="aaa",是以還是aaa。

第二段的答案因為正如上面所言,清單和字典是可更改對象,是以修改一個指向的對象時會把類變量也改變了。

2.4.3 自我實踐題

讀者若有時間,可以從W3school的Python 100例中學習Python的各種應用基礎知識,網址是:

https://www.w3cschool.cn/python/python-100-examples.html