天天看點

(入門三)Python爬動态頁面之爬小說

前言

動态頁面相對于靜态頁面的解析來說,更加簡單直接,因為動态頁面傳回的ajax資料基本都是json格式或者經過去頭或者去尾變成json,根本不需要依賴BeautifulSoup,如下為需要處理的json:

隻要找到請求的規律,後續就會水到渠成

分析請求

本次依然以上篇文章中提到的網站為例,該網站可以點選"全文閱讀"實作滾動滑鼠閱讀,很明顯是動态加在的,不廢話,打開小說頁面,點選全文閱讀

(入門三)Python爬動态頁面之爬小說

按下F12,點選Network,過濾設定為XHR,滑鼠往下滾動,攔截到:

(入門三)Python爬動态頁面之爬小說

點選Response,可以看到傳回的是标準json資料:

(入門三)Python爬動态頁面之爬小說
(入門三)Python爬動态頁面之爬小說

可以看到,傳回的json資料中,章節名為

response['data']['chapterName']

,文章内容為

response['data']['content']

,但是文章内容中帶有p标簽,簡單,用re正則去掉!

文章内容解析成功了,如何請求下一章的内容呢?

我們翻回來看一下攔截的Headers,往下翻,可以看到ajax請求的參數:

(入門三)Python爬動态頁面之爬小說

再結合網頁的網址http://xxx.com/chapter/898410/58676024.html

你會發現bookId就在網址上:

url.split('/')[-2]

,那

chapterId

呢?此時再連續翻兩章,攔截兩個包來對比一下,有心的你就會發現,上一章攔截的

response['data']['nexCid']

為下一章Headers請求參數裡面的

chapterId

,好,下一章的

chapterId

也知道了,那

_:1578574655825

這個是個啥呢?對,經驗告訴我們這個參數很可能是時間戳,格式化一下看看!

(入門三)Python爬動态頁面之爬小說

嗯,的确是時間戳了!

那如何判斷最後一章呢,從倒數第二章開始全文閱讀,拉到最後,攔截請求,可以看到,最後的**

response['data']['nexCid']

值為0,就把它作為循環結束的條件。

實作

至此,邏輯非常清楚了:

章節名:

response['data']['chapterName']

文章内容:

response['data']['nexCid']

下一章請求頭的chapterId:

response['data']['nexCid']

剩下的就是實作了:

import requests
import os
import re
import time
import json

def spiderBookdynamic(url: str):    
    nexCid = url.split('/')[-1].replace('.html', '')
    bookid = url.split('/')[-2]
    path = 'E:/Ebooks2/' + bookid
    if not os.path.exists(path):
        os.makedirs(path)
    pathAllinOne: str = path + '/' + bookid + '(合并).txt'
    while True:
    	# 13位時間戳
        timestamp = int(round(time.time() * 1000))
        # 構造ajax頭
        url = 'http://book.zongheng.com/api/chapter/chapterinfo'
        params = {
            'bookId': bookid,
            'chapterId': nexCid,
            '_': timestamp
        }
        res = requests.get(url, params=params)
        res.encoding = 'utf-8'
        response = json.loads(res.text)
        chaptername = '\n' + response['data']['chapterName']+ '\n\n\n'
        content = chaptername + '\n'.join(re.findall('<p>(.*?)</p>', response['data']['content'], re.S))
        nexCid = response['data']['nexCid']

        # 寫入章節
        with open(path + '/' + chaptername.strip() + '.txt', 'w') as f:
            f.write(content)
            print("已儲存章節:" + chaptername.strip())
        # 寫入合并
        with open(pathAllinOne, 'a') as f:
            f.write(content)
		# 最後一章
        if nexCid == 0:
            return

if __name__ == '__main__':
    url = 'http://xxx.com/chapter/898410/58676024.html'
    spiderBookdynamic(url)