简书搜索爬虫
這期的爬蟲是爬取“簡書”的搜索結果頁,篇幅將會分為兩部分來寫,第一部分是爬蟲部分,主要涉及搜索文章的提取和數據保存,第二部分涉及基本的數據分析和可視化,本篇文章屬于爬蟲篇。
爬蟲源代碼
首先看一下整個爬蟲的源代碼,每個函數的用處已經寫在函數說明中,后面也會進行代碼解讀。
# -*- coding: utf-8 -*- import requests import json from urllib.parse import quote from pymongo import MongoClient""" 簡書搜索爬蟲 輸入搜索關鍵詞,將搜索到的所有文章爬取下來 數據保存到 mongodb 中 """class JianshuSearch(object):def __init__(self, db_name, coll_name, key, host='127.0.0.1', port=27017):self.headers = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) ""Chrome/57.0.2987.110 Safari/537.36"}self.url = 'http://www.jianshu.com/search/do?q={key}&type=note&page={page}&order_by=default'self.key = quote(key)self.start_page = 1self.host = hostself.port = portself.db_name = db_nameself.coll_name = coll_namedef get_total_pages(self):'''提取總頁碼數'''url = self.url.format(key=self.key, page=self.start_page)html = requests.get(url, headers=self.headers).textdata = json.loads(html)total_pages = data['total_pages']return total_pagesdef get_infos(self, page):'''提取單個頁面的文章信息,格式為dict'''url = self.url.format(key=self.key, page=page)html = requests.get(url, headers=self.headers).textdata = json.loads(html)entries = data['entries']for each in entries:self.save_infos(each)def save_infos(self, entry):'''保存一個文章的信息'''coon = MongoClient(host=self.host, port=self.port)coll = coon[self.db_name][self.coll_name]coll.insert(entry)def main(self):'''主函數,循環迭代進行翻頁,提取所有頁碼的信息并保存到數據庫'''total_pages = int(self.get_total_pages())for i in range(1, total_pages + 1):self.get_infos(i)print('總計{}頁,已經爬完{}頁'.format(total_pages, i))if __name__ == '__main__':DB_NAME = 'jianshu'COLL_NAME = 'search_result'key = 'python'spider = JianshuSearch(key=key, db_name=DB_NAME, coll_name=COLL_NAME)spider.main()爬蟲思路
基本思路
爬蟲的基本思路依然分為3個主要步驟:
查看頁面主要信息
首先在簡書的搜索框中輸入任意一個關鍵詞,例如“Python”,然后點擊搜索按鈕,查看結果頁面。
結果頁面如下圖所示:
可以看到,搜索的結果包含了很多種類的信息,有“相關用戶”、“相關專題”和“相關文章”,并且文章的排序還可以選擇條件。
由于這里只需要提取搜索文章的信息,因此可以先看一下搜索到的文章列表中包含哪些可以收集的信息,以便后續查找和保存數據。
找到入口——第一個 URL
當然,一般來說,很多時候,我們看到的信息其實并不是眼前的頁面給我們的信息,而是當前頁面從其他地方“搬”過來的信息。如果使用或者知道ajax 的用法,這句話就很好理解,當然,不理解也無妨,并不影響后續操作。
打開瀏覽器的開發者界面,可以使用快捷鍵 F12。刷新一下搜索的頁面,然后進入 Network,看看瀏覽器中加載了什么頁面。
一般可以先從 Doc中查看,也就是網頁源代碼,但是這次的爬蟲可以看到源代碼中并沒有搜索的結果頁,于是可以繼續查看 js,發現好像也沒有新加載頁面,繼續查看 XHR,終于找到了刷新頁面加載出來的頁面請求,具體看截圖:
看截圖中的編號,編號1就是頁面加載的地方,編號2可以看到請求的 URL,編號3就是 URL 的組成,可以從中查看鏈接的構成規律,這里的規律就是鏈接中有2個關鍵參數,第一個參數就是搜索的關鍵詞,這里用 q=Python表示,然后第二個參數就是當前頁碼,這里是 page=2,從這里就可以直接聯想到,如果知道總頁碼數,那就可以使用循環來得到所有頁碼的 URL。編號4是請求的方式,這里是 GET。
選擇翻頁方式
經過這個頁面,就可以把整個爬蟲的思路理清楚了:
- 首先,想辦法找到總頁碼數
- 然后提取單頁的信息,并且保存到數據庫中
- 使用循環方式,提取所有頁的信息
源碼解讀
首先需要導入相關庫:
import requests import json from urllib.parse import quote from pymongo import MongoClient這4個庫的作用分別是:
爬蟲類的創建
由于這個爬蟲是創建了一個爬蟲類,所以需要按照 Python類的規范來,首先初始化類,通過函數來實現:
def __init__(self, db_name, coll_name, key, host='127.0.0.1', port=27017):self.headers = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) ""Chrome/57.0.2987.110 Safari/537.36"}self.url = 'http://www.jianshu.com/search/do?q={key}&type=note&page={page}&order_by=default'self.key = quote(key)self.start_page = 1self.host = hostself.port = portself.db_name = db_nameself.coll_name = coll_name這里給類傳遞了5個參數,其中3個是沒有給予默認值的參數,2個是給了默認值的參數,每個參數的含義:
- key:搜索的關鍵詞
- db_name:數據庫名稱
- coll_name:數據表名稱
- host,port:鏈接數據庫的地址和端口
提取總頁碼數
可以通過爬取任意一個頁碼,然后打印一下提取的信息,看看信息的構成。
通過打印信息可以發現,每個頁面的信息都是一個字典格式,因此可以通過json模塊來轉換成 Python 的 dict 格式,然后可以發現每頁都有一個參數是“total_pages”,這個參數就提供了當前搜索的結果總頁碼數,因此可以通過函數來提取這個參數的值:
def get_total_pages(self):'''提取總頁碼數'''url = self.url.format(key=self.key, page=self.start_page)html = requests.get(url, headers=self.headers).textdata = json.loads(html)total_pages = data['total_pages']return total_pages提取當個頁面的信息,并保存到數據庫
由于每個頁面的信息都是一個 json 格式,所以信息的提取方式很簡單,直接從字典中提取就行了:
def get_infos(self, page):'''提取單個頁面的文章信息,格式為dict'''url = self.url.format(key=self.key, page=page)html = requests.get(url, headers=self.headers).textdata = json.loads(html)entries = data['entries']for each in entries:self.save_infos(each)函數的思路很簡單,首先通過 requests 請求網頁,然后得到一個json類型的信息,但是由于這個信息的格式是 str, 所以需要使用 json.loads 方法轉換成 dict 格式。然后使用字典的鍵值對關系提取到總頁碼數就可以了。
這個函數的最后面用到了一個保存信息的函數,也就是后面要說的將數據保存到數據庫中。
def save_infos(self, entry):'''保存一個文章的信息'''coon = MongoClient(host=self.host, port=self.port)coll = coon[self.db_name][self.coll_name]coll.insert(entry)保存到數據庫的函數需要傳入一個參數,是一個 dict 類型,這個參數正好可以理解為提取的單個文章的信息。
首先,按照 mongodb 的連接方式建立一個連接,這個連接就使用到了創建類的時候傳入的數據庫的參數,然后使用 insert()方法就可以插入數據了。
循環提取所有頁面的信息
講過上述的的函數,已經可以提取總頁碼數,也可以提取并保存單個頁碼的文章信息了,剩下的就是使用循環來提取所有頁碼的信息了,于是,可以把這個過程寫到一個主函數中:
def main(self):'''主函數,循環迭代進行翻頁,提取所有頁碼的信息并保存到數據庫'''total_pages = int(self.get_total_pages())for i in range(1, total_pages + 1):self.get_infos(i)print('總計{}頁,已經爬完{}頁'.format(total_pages, i))為了方便查看爬蟲的進度,在每爬取一頁信息,可以打印當前的進度。
運行爬蟲
最后一段代碼就是運行爬蟲,首先給定一些需要傳遞到爬蟲類中的參數,然后啟動爬蟲的主程序即可看到爬蟲結果。
查看數據庫中信息
“Python”這個字段在簡書中有100頁的數據(如果沒有猜錯,這個100頁應該是簡書默認提供的最大頁碼數),所以爬蟲運行的時間并不長,爬完之后可以使用可視化工具看看數據庫中的信息。
數據庫中信息如圖:
后記:從數據庫中可以查看到一些有效信息,包括文字的標題、鏈接、發布時間、作者的信息、評論數、閱覽量、喜歡數等。雖然這些數據并沒有什么研究價值,但是本著練手的想法,后續會使用 Python 基本的數據分析工具來對爬取的信息進行可視化分析。
查看原文
轉載于:https://www.cnblogs.com/gopythoner/p/7760548.html
總結
- 上一篇: angular的uiRouter服务学习
- 下一篇: myeclipse上进行tomcat远程