前言
看小說是我這麼多年來一直保持的習慣。《盤龍》、《鬥破蒼穹》、《仙逆》、《凡人修仙傳》等等,陪伴了我整個學生時代。最近發現iOS上小說類app體驗都不好,經常出現廣告彈出、更新不及時、強制分享等情況。於是在一個下雨的晚上,我決定不再忍受這些app,自己強擼一個追書爬蟲。
Scrapy介紹
Scrapy是python主流爬蟲框架,可以很方便的通過url抓取web資訊,同時與傳統的requests庫相比,提供了更多的工具和更高的併發。推薦從官方學習網站上學習。
不過,你一點scrapy資料都不知道也沒有關係,讀完本文一樣能擼出來
Scrapy實戰
在開始前,我們需要準備好以下幾個東西:
- 想要爬取的小說url
- 環境搭建
- 入門級的python語法
選取網站
這裡我選的是 m.book9.net/。 選這個網站是因為它有是三個優點
- 更新速度比較快 (服務穩定)
- 頁面的結構簡單 (易於解析)
- 沒有做一些防爬蟲的保護 (操作簡單)
接下來,找到追更小說的主頁。
比如 辰東的《聖墟》
假設現在我們要追更的話,需要每次開啟這個網站,然後點選最新章節的第一個選項條,連結到具體的小說章節。
仿造以上的步驟,我畫出了這樣一個流程:
所以接下來,我們只需要根據這些流程來轉化成我們的程式碼就好了
搭建工程
我們將要搭建一個Scrapy殼工程,在這之前要先確保自己安裝了python的環境。框架自身相容2、3版本,所以不需要擔心版本的差異。
我本地的環境是python3,所以可能會和2有細微的差異操作。
1.安裝Scrapy
> pip3 install scrapy
複製程式碼
2.建立爬蟲工程,將其命名為NovelCrawler
> scrapy startproject NovelCrawler
複製程式碼
3. 建立一個基於 url 的爬蟲服務
> scrapy genspider novel m.book9.net
複製程式碼
以上就是基本的工程建立過程,執行完畢之後就可以使用
> scrapy crawl novel
複製程式碼
命令去開啟爬蟲服務。不過當前我們的爬蟲還沒有實現任何的規則,所以即使執行了命令也不會做任何事,所以我們需要在工程中新增一些爬蟲規則。
爬蟲編寫
接下來我們用Pycharm來開啟剛剛建立好的工程。
scrapy的所有爬蟲服務都集中在spiders目錄下,我們也在這裡添爬蟲檔案novel.py
請求小說主頁
我們開啟檔案,新增一些基礎的配置
# encoding:utf-8
import scrapy
class NovelSpider(scrapy.Spider):
#配置服務名稱,與上文建立服務的名稱相同
name = `novel`
#允許訪問的域,與上文建立服務的名稱相同
allowed_domains = [`m.book9.net`]
#發起請求的url,《聖墟》小說主頁
start_urls = [`https://m.book9.net/wapbook/10.html`]
#預設的請求成功的回撥函式
def parse(self, response):
pass
複製程式碼
上面的程式碼中,parse函式的入引數response物件裡面有什麼引數對我們來說是未知的,這也是初學python很頭疼的地方。這裡給大家提供一個方法:用Pycharm的debug功能檢視引數
從上圖中我們可以發現,response包含了請求的html資訊。因此我們只需要其稍加處理,擷取出我們需要的部分。
獲取最新章節url
那麼如何解析我們需要的節點呢,response給我們提供了
xpath方法,我們只需要輸入的xpath規則就可以定位到相應html標籤節點。
不會xpath語法沒關係,Chrome給我們提供了一鍵獲取xpath地址的方法(右鍵->檢查->copy->copy xpath),如下圖:
通過xpath,我們可以從這個頁面獲取到最新章節的地址
# encoding:utf-8
import scrapy
class NovelSpider(scrapy.Spider):
name = `novel`
allowed_domains = [`m.book9.net`]
start_urls = [`https://m.book9.net/wapbook/10.html`]
def parse(self, response):
#指定的<a>標籤的跳轉連結
context = response.xpath(`/html/body/div[3]/div[2]/p[1]/a/@href`)
#提取陣列的第一個結果 即最新章節的url
url = context.extract_first()
print(url)
pass
複製程式碼
請求章節資訊
有了連結之後,我們就可以跳轉到下一個頁面。而response也提供了follow方法,便於我們在站內進行短鏈的跳轉。
# encoding:utf-8
import scrapy
class NovelSpider(scrapy.Spider):
name = `novel`
allowed_domains = [`m.book9.net`]
start_urls = [`https://m.book9.net/wapbook/10.html`]
def parse(self, response):
context = response.xpath(`/html/body/div[3]/div[2]/p[1]/a/@href`)
url = context.extract_first()
#獲取短鏈後繼續請求,並將結果返回指定的回撥
yield response.follow(url=url, callback=self.parse_article)
#自定義回撥方法
def parse_article(self,response):
#這裡的response 就是我們具體的文章頁
print(response)
pass
複製程式碼
(如對程式碼中關鍵字yield感到疑惑的請點選傳送門)
有了文章的頁面,我們只需要對他的html進行解析。這部分內容過於面向細節。只適用於這個網站,因此我不過多進行贅述。附上註釋程式碼:
# encoding:utf-8
import re
import os
import scrapy
class NovelSpider(scrapy.Spider):
name = `novel`
allowed_domains = [`m.book9.net`]
start_urls = [`https://m.book9.net/wapbook/10.html`]
def parse(self, response):
# 指定的<a>標籤的跳轉連結
context = response.xpath(`/html/body/div[3]/div[2]/p[1]/a/@href`)
#獲取短鏈後繼續請求,並將結果返回指定的回撥
url = context.extract_first()
yield response.follow(url=url, callback=self.parse_article)
def parse_article(self, response):
#獲取文章的標題
title = self.generate_title(response)
#構建文章的html
html = self.build_article_html(title, response)
#將章節html存至本地
self.save_file(title + ".html", html)
#用自帶的瀏覽器開啟本地html
os.system("open " + title.replace(" ", " ") + ".html")
pass
@staticmethod
def build_article_html(title, response):
#獲取文章內容
context = response.xpath(`//*[@id="chaptercontent"]`).extract_first()
#過略文章中<a> 標籤跳轉內容
re_c = re.compile(`<s*a[^>]*>[^<]*<s*/s*as*>`)
article = re_c.sub("", context)
#拼接文章html
html = `<html><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><div align="center" style="width:100%;text-alight:center"><b><font size="5">`
+ title + `</font></b></div>` + article + "</html>"
return html
@staticmethod
def generate_title(response):
title = response.xpath(`//*[@id="read"]/div[1]/text()`).extract()
return "".join(title).strip()
@staticmethod
def save_file(file_name, context):
fh = open(file_name, `wb`)
fh.write(context.encode(encoding="utf-8"))
fh.close()
pass
複製程式碼
現在我們可在再當前目錄下執行以下命令:
> scrapy crawl novel
複製程式碼
展示視訊
思考
整體寫完下來,發現很難做到一份程式碼適用於多個站點。因此遇到在多站點抓取的需求時,為每個站點建立一個爬蟲檔案會更為適合。
原始碼地址(聽說年底點了star的年終會加倍哦)