建議: 請在電腦的陪同下,閱讀本文。本文以實戰為主,閱讀過程如稍有不適,還望多加練習。
網絡爬蟲簡介
網絡爬蟲,也叫網絡蜘蛛(Web Spider)。它根據網頁地址(URL)爬取網頁內容,而網頁地址(URL)就是我們在瀏覽器中輸入的網站鏈接。比如:https://www.baidu.com/,它就是一個 URL。
在講解爬蟲內容之前,我們需要先學習一項寫爬蟲的必備技能: 審查元素(如果已掌握,可跳過此部分內容) 。
1、審查元素
在瀏覽器的地址欄輸入 URL 地址,在網頁處右鍵單擊,找到檢查。(不同瀏覽器的叫法不同,Chrome 瀏覽器叫做檢查,Firefox 瀏覽器叫做查看元素,但是功能都是相同的)
Python3 網絡爬蟲快速入門實戰解析
我們可以看到,右側出現了一大推代碼,這些代碼就叫做 HTML。什麼是 HTML?舉個容易理解的例子: 我們的基因決定了我們的原始容貌,服務器返回的 HTML 決定了網站的原始容貌。
Python3 網絡爬蟲快速入門實戰解析
為啥說是 原始容貌 呢?因為人可以整容啊!扎心了,有木有? 那網站也可以"整容"嗎?可以!請看下圖:
Python3 網絡爬蟲快速入門實戰解析
我能有這麼多錢嗎?顯然不可能。我是怎麼給網站"整容"的呢?就是通過修改服務器返回的 HTML 信息。我們每個人都是"整容大師",可以修改頁面信息。 我們在頁面的哪個位置點擊審查元素,瀏覽器就會為我們定位到相應的 HTML 位置,進而就可以在本地更改 HTML 信息。
再舉個小例子:我們都知道,使用瀏覽器"記住密碼"的功能,密碼會變成一堆小黑點,是不可見的。可以讓密碼顯示出來嗎?可以,只需給頁面"動個小手術"!以淘寶為例,在輸入密碼框處右鍵,點擊檢查。
Python3 網絡爬蟲快速入門實戰解析
可以看到,瀏覽器為我們自動定位到了相應的 HTML 位置。將下圖中的 password 屬性值改為 text 屬性值(
直接在右側代碼處修改 ):Python3 網絡爬蟲快速入門實戰解析
我們讓瀏覽器記住的密碼就這樣顯現出來了:
Python3 網絡爬蟲快速入門實戰解析
說這麼多,什麼意思呢? 瀏覽器就是作為客戶端從服務器端獲取信息,然後將信息解析,並展示給我們的。 我們可以在本地修改 HTML 信息,為網頁"整容",但是我們修改的信息不會回傳到服務器,服務器存儲的 HTML 信息不會改變。刷新一下界面,頁面還會回到原本的樣子。 這就跟人整容一樣,我們能改變一些表面的東西,但是不能改變我們的基因。
2、簡單實例
網絡爬蟲的第一步就是根據 URL,獲取網頁的 HTML 信息。在 Python3 中,可以使用 urllib.request 和 requests 進行網頁爬取。
urllib 庫是 python 內置的,無需我們額外安裝,只要安裝了 Python 就可以使用這個庫。
requests 庫是第三方庫,需要我們自己安裝。這個庫強大好用,所以本文使用 requests 庫獲取網頁的 HTML 信息。requests 庫的 github 地址:https://github.com/requests/requests
(1)requests 安裝
在 cmd 中,使用如下指令安裝 requests:
<code>1pip install requests/<code>
requests 庫的基礎方法如下:
Python3 網絡爬蟲快速入門實戰解析
官方中文教程地址:http://docs.python-requests.org/zh_CN/latest/user/quickstart.html
requests 庫的開發者為我們提供了詳細的中文教程,查詢起來很方便。本文不會對其所有內容進行講解,摘取其部分使用到的內容,進行實戰說明。
首先,讓我們看下 requests.get()方法,它用於向服務器發起 GET 請求,不瞭解 GET 請求沒有關係。我們可以這樣理解:get 的中文意思是得到、抓住,那這個 requests.get()方法就是從服務器得到、抓住數據,也就是獲取數據。讓我們看一個例子(以 www.gitbook.cn 為例)來加深理解:
<code>1# -*- coding:UTF-8 -*-
2import requests
3
4if __name__ == '__main__':
5 target = 'http://gitbook.cn/'
6 req = requests.get(url=target)
7 print(req.text)/<code>
requests.get()方法必須設置的一個參數就是 url,因為我們得告訴 GET 請求,我們的目標是誰,我們要獲取誰的信息。運行程序看下結果:
Python3 網絡爬蟲快速入門實戰解析
左側是我們程序獲得的結果,右側是我們在 www.gitbook.cn 網站審查元素獲得的信息。我們可以看到,我們已經順利獲得了該網頁的 HTML 信息。這就是一個最簡單的爬蟲實例,可能你會問,我只是爬取了這個網頁的 HTML 信息,有什麼用呢?客官稍安勿躁,接下來進入我們的實戰正文。
爬蟲實戰
接下來我們來一次爬蟲實戰,爬取中網小說網站「筆趣看」上的文字。
(1)實戰背景
小說網站-筆趣看:
URL:http://www.biqukan.com/
筆趣看是一個盜版小說網站,這裡有很多起點中文網的小說,該網站小說的更新速度稍滯後於起點中文網正版小說的更新速度。並且該網站只支持在線瀏覽,不支持小說打包下載。因此,本次實戰就是從該網站爬取並保存一本名為《一念永恆》的小說,該小說是耳根正在連載中的一部玄幻小說。PS:本實例僅為交流學習,支持耳根大大,請上起點中文網訂閱。
(2)小試牛刀
我們先看下《一念永恆》小說的第一章內容,URL:http://www.biqukan.com/1_1094/5403177.html
Python3 網絡爬蟲快速入門實戰解析
我們先用已經學到的知識獲取 HTML 信息試一試,編寫代碼如下:
<code>1# -*- coding:UTF-8 -*-
2import requests
3
4if __name__ == '__main__':
5 target = 'http://www.biqukan.com/1_1094/5403177.html'
6 req = requests.get(url=target)
7 print(req.text)/<code>
運行代碼,可以看到如下結果:
Python3 網絡爬蟲快速入門實戰解析
可以看到,我們很輕鬆地獲取了 HTML 信息。但是,很顯然,很多信息是我們不想看到的,我們只想獲得如右側所示的正文內容,我們不關心 div、br 這些 html 標籤。 如何把正文內容從這些眾多的 html 標籤中提取出來呢?這就是本次實戰的主要內容。
(3)Beautiful Soup
爬蟲的第一步,獲取整個網頁的 HTML 信息,我們已經完成。接下來就是爬蟲的第二步,解析 HTML 信息,提取我們感興趣的內容。對於本小節的實戰,我們感興趣的內容就是文章的正文。提取的方法有很多,例如使用正則表達式、Xpath、Beautiful Soup 等。對於初學者而言,最容易理解,並且使用簡單的方法就是使用 Beautiful Soup 提取感興趣內容。
Beautiful Soup 的安裝方法和 requests 一樣,使用如下指令安裝(也是二選一):
- pip install beautifulsoup4
- easy_install beautifulsoup4
一個強大的第三方庫,都會有一個詳細的官方文檔。我們很幸運,Beautiful Soup 也是有中文的官方文檔。URL:
http://beautifulsoup.readthedocs.io/zh_CN/latest/
同理,我會根據實戰需求,講解 Beautiful Soup 庫的部分使用方法,更詳細的內容,請查看官方文檔。
現在,我們使用已經掌握的審查元素方法,查看一下我們的目標頁面,你會看到如下內容:
Python3 網絡爬蟲快速入門實戰解析
不難發現,文章的所有內容都放在了一個名為 div 的“東西下面”,這個"東西"就是 html 標籤。HTML 標籤是 HTML 語言中最基本的單位,HTML 標籤是 HTML 最重要的組成部分。不理解,沒關係,我們再舉個簡單的例子:
一個女人的包包裡,會有很多東西,她們會根據自己的習慣將自己的東西進行分類放好。鏡子和口紅這些會經常用到的東西,會歸放到容易拿到的外側口袋裡。那些不經常用到,需要注意安全存放的證件會放到不容易拿到的裡側口袋裡。
html 標籤就像一個個“口袋”,每個“口袋”都有自己的特定功能,負責存放不同的內容。顯然,上述例子中的 div 標籤下存放了我們關心的正文內容。這個 div 標籤是這樣的:
<code>1/<code>細心的朋友可能已經發現,除了 div 字樣外,還有 id 和 class。id 和 class 就是 div 標籤的屬性,content 和 showtxt 是屬性值,一個屬性對應一個屬性值。這東西有什麼用?它是用來區分不同的 div 標籤的,因為 div 標籤可以有很多,我們怎麼加以區分不同的 div 標籤呢?就是通過不同的屬性值。
仔細觀察目標網站一番,我們會發現這樣一個事實: class 屬性為 showtxt 的 div 標籤,獨一份!這個標籤裡面存放的內容,是我們關心的正文部分。
知道這個信息,我們就可以使用 Beautiful Soup 提取我們想要的內容了,編寫代碼如下:
<code> 1# -*- coding:UTF-8 -*-
2from bs4 import BeautifulSoup
3import requests
4if __name__ == "__main__":
5 target = 'http://www.biqukan.com/1_1094/5403177.html'
6 req = requests.get(url = target)
7 html = req.text
8 bf = BeautifulSoup(html)
9 texts = bf.find_all('div', class_ = 'showtxt')
10 print(texts)/<code>在解析 html 之前,我們需要創建一個 Beautiful Soup 對象。BeautifulSoup 函數里的參數就是我們已經獲得的 html 信息。然後我們使用 find_all 方法,獲得 html 信息中所有 class 屬性為 showtxt 的 div 標籤。 find_all 方法的第一個參數是獲取的標籤名,第二個參數 class_ 是標籤的屬性,為什麼不是 class,而帶了一個下劃線呢?因為 python 中 class 是關鍵字,為了防止衝突,這裡使用 class_ 表示標籤的 class 屬性, class_ 後面跟著的 showtxt 就是屬性值了。看下我們要匹配的標籤格式:
<code>1/<code>這樣對應的看一下,是不是就懂了?可能有人會問了,為什麼不是 find_all('div', id = 'content', class_ = 'showtxt') ?這樣其實也是可以的,屬性是作為查詢時候的約束條件,添加一個 class_='showtxt' 條件,我們就已經能夠準確匹配到我們想要的標籤了,所以我們就不必再添加 id 這個屬性了。運行代碼查看我們匹配的結果:
Python3 網絡爬蟲快速入門實戰解析
我們可以看到,我們已經順利匹配到我們關心的正文內容,但是還有一些我們不想要的東西。比如 div 標籤名,br 標籤,以及各種空格。怎麼去除這些東西呢?我們繼續編寫代碼:
<code> 1# -*- coding:UTF-8 -*-
2from bs4 import BeautifulSoup
3import requests
4if __name__ == "__main__":
5 target = 'http://www.biqukan.com/1_1094/5403177.html'
6 req = requests.get(url = target)
7 html = req.text
8 bf = BeautifulSoup(html)
9 texts = bf.find_all('div', class_ = 'showtxt')
10 print(texts[0].text.replace('\\\\xa0'*8,'\\n\\n'))/<code>find_all 匹配的返回的結果是一個列表。提取匹配結果後,使用 text 屬性,提取文本內容,濾除 br 標籤。隨後使用 replace 方法,剔除空格,替換為回車進行分段。 在 html 中是用來表示空格的。 replace('\\\\xa0'*8,'\\n\\n') 就是去掉下圖的八個空格符號,並用回車代替:
Python3 網絡爬蟲快速入門實戰解析
程序運行結果如下:
Python3 網絡爬蟲快速入門實戰解析
可以看到,我們很自然的匹配到了所有正文內容,並進行了分段。我們已經順利獲得了一個章節的內容,要想下載正本小說,我們就要獲取每個章節的鏈接。我們先分析下小說目錄:URL:http://www.biqukan.com/1_1094/
Python3 網絡爬蟲快速入門實戰解析
通過審查元素,我們發現可以發現,這些章節都存放在了 class 屬性為 listmain 的 div 標籤下,選取部分 html 代碼如下:
<code> 1/<code>
2
3- 《一念永恆》最新章節列表
4
5
6
7
8
9
10
11
12
13
14
15
16- 《一念永恆》正文卷
17
18
19
20
21在分析之前,讓我們先介紹一個概念:父節點、子節點、孫節點。
和限定了標籤的開始和結束的位置,他們是成對出現的,有開始位置,就有結束位置。我們可以看到,在標籤包含標籤,那這個
標籤就是
標籤的子節點,標籤又包含
- 標籤和
- 標籤,那麼
- 標籤和
- 標籤就是
標籤的孫節點。有點繞?那你記住這句話: 誰包含誰,誰就是誰兒子!他們之間的關係都是相對的。比如對於
- 標籤,它的子節點是
閱讀更多 編程樂園 的文章