一、前言簡述
因為最近微信讀書出了網頁版,加上自己也在閑暇的時候看了兩本書,不禁好奇什么樣的書更受歡迎,哪位作者又更受讀者喜歡呢?話不多說,爬一下就能有個了解了。
二、頁面分析
首先打開微信讀書:https://weread.qq.com/,往下拉之后可以看到有榜單推薦,而且顯示總共有25個榜單,有的榜單只有幾百本,有的榜單卻有幾萬本書。

打開“文學藝術榜”,可以看到一頁顯示了20條書本信息,下拉之后很容易就能發現這些書本信息是通過 AJAX 來加載的。

更關鍵的是,要獲取這些書籍信息,只需要得到分類 ID 和參數 maxIndex。不過測試發現,每個分類只會返回50個頁面的內容,也就是最多一千條書本信息。那么,如果只有這25個類別的榜單,能得到的數據還是有點少的,所以要怎么得到更多的數據呢?
細心的人可以發現右側還能選擇類別!如下圖:

不過,查看這些元素發現里面是沒有顯示 URL 的,如下圖:

但是這也不表示沒有辦法了,全局搜索一下就能找到了,如下圖:

CategoryId 就是這個分類的 ID,也就是 URL 中“bookListInCategory/”后面的內容。至於 maxIndex,可以先設為0,然后發送請求得到這一分類的書本總數“totalCount”,然后根據這個書本總數是否超過一千來設置頁數,就能得到這一分類下能夠爬取到的所有 URL 了。
三、爬取步驟
前面經過分析已經知道只要拿到書本分類 ID,就能發送請求得到書本總數,也就能構造該分類下的所有頁面的 URL 了。那要怎么得到所有分類呢?前面全局搜索的時候已經搜到了書本分類的 CategoryId 等信息,如下圖:

所以只需先請求頁面然后用正則匹配 CategoryId 就行了!然后對每個分類發送一次請求,用於獲取書本總數,並構造這一分類下的所有 URL。這一部分代碼如下:
1 def prepare(base_url="https://weread.qq.com/web/category/1700000") -> list: 2 """ 3 prepare for crawler 4 :param base_url: weread base url 5 :return: page url list 6 """ 7 def request(url) -> list: 8 """ 9 request function 10 :param url: url 11 :return: page url list 12 """ 13 page_urls = [] 14 try: 15 res = requests.get(url=url, headers=headers) 16 if res.status_code == 200: 17 count = res.json()["totalCount"] 18 cnt = 50 if count >= 1000 else count // 20 19 page_urls = [url + "?maxIndex={}".format(i * 20) for i in range(cnt)] 20 else: 21 logging.error("Error request!") 22 except Exception as e: 23 logging.error(e) 24 finally: 25 return page_urls 26 27 resp = requests.get(url=base_url, headers=headers) 28 # check status code 29 if resp.status_code == 200: 30 id_list = re.findall('"CategoryId":"(.+?)"', resp.text) 31 id_list = list(set([i for i in id_list if i[0].isdigit()])) 32 href_list = ["https://weread.qq.com/web/bookListInCategory/{}".format(i) for i in id_list] 33 result = [] 34 for href in href_list: 35 result += request(href) 36 logging.info("Url count: {}".format(len(result))) 37 return result 38 else: 39 logging.error("Prepare error!") 40 exit()
進行到這一步,后面就很簡單了,就是獲取請求結果並解析即可。程序運行時打印輸出如下:

可以看到總鏈接數有7091條,那么爬到的書本信息有多少條呢?因為我用的是 MongoDB 保存的,所以打開 Robot3T 查看,總共有141137條,結果如下圖:

四、繪圖分析
熟悉 Python 的都知道,matplotlib 是 Python 中用的最多的 2D 圖形繪圖庫。不過我在這推薦一個好用的第三方庫:pyecharts,這是一個用於生成 Echarts 圖表的類庫,生成的圖表更加精巧,可視化效果更好,不過需要注意的是 pyecharts 的0.5版本和1.0版本使用方法是不同的。下面就是使用這個庫生成的橫向柱狀圖了,分別表示評分前十的書籍、閱讀量前十的書籍和總閱讀量前十的作者:



可以發現評分高的書籍閱讀量卻不一定高,閱讀量更多的往往是一些網絡小說。為什么好像現在名著都不怎么討喜,而網絡小說卻能讓更多人着迷呢?個人猜想是小說里的世界可能更加能夠滿足現在年輕人的幻想吧,現實生活疲憊不堪,就會更加迷戀小說中的“世外桃源”吧。
完整代碼已上傳到 GitHub!
