從本章開始,咱們將要開始進入最後的案例實踐篇。html
在爬取數據以後,咱們通常會怎麼用數據呢?通常來說,咱們可能會作一個搜索引擎,好比說咱們爬了新聞,可能會作一個新聞的搜索;爬取了小說可能作一個小說的搜索。python
本案例將要爬取北科貼吧的帖子數據,並在此基礎上構建一個簡單的搜索功能。數據庫
這裏咱們首先打開北京科技大學
的百度貼吧:tieba.baidu.com/f?kw=北京科技大學app
咱們的目標是關注帖子的標題名稱,好比這個:「北郵人下載須要流量嗎」
,「請問一下學長學姐,全國大學生數學競賽初賽全國一等獎在我們學校」
。工具
還有就是咱們確定不能只爬取一頁的信息,這裏咱們將要爬取前1000頁的信息。網站
首先咱們打開Chrome開發者工具看一下列表如何解析。搜索引擎
這裏咱們選中一個標題名稱後,能夠直接看到一個a
標籤,它的class爲j_th_tit
。spa
因此使用如下代碼就能夠打印出全部的標題來。3d
soup = BeautifulSoup(resp.content, "html.parser")
items = soup.find_all("a", {"class", "j_th_tit"})
for a in items:
title = item.get_text()
print(title)
複製代碼
頁面分析完了以後就能夠分析一下分頁了,咱們把小箭頭晃到底部分頁的位置。code
能夠發現分頁對應的網址主要是pn的值不同。第2頁對應50,第3頁對應100,第4頁對應150。
也就是,$$pn=(page-1)*50$$這樣的關係。
完成以上的分析工做以後,就能夠開始實現咱們的爬蟲了。
首先是數據庫的操做,這裏使用到tieba
數據庫的beike
集合。而後保存文檔的話就直接insert就行了。
def init_collection():
client = pymongo.MongoClient(host="localhost", port=27017)
db = client['tieba']
return db["beike"]
def save_docs(docs):
beike.insert(docs)
beike = init_collection()
複製代碼
下面,咱們不編寫worker,而是先進行任務的初始化。
if __name__ == '__main__':
crawler = SimpleCrawler(5)
crawler.add_worker("worker", worker)
for i in range(1, 11):
crawler.add_task({"id": "worker", "page": i})
crawler.start()
複製代碼
這裏咱們首先初始化SimpleCrawler
,而後給添加worker
以及task
。
關於task,能夠看到上面的代碼經過循環,添加了10個任務,每一個任務的page屬性不同。worker確定是爬取某一頁並解析加入數據庫的代碼,咱們這裏其實就是添加了爬取前10頁的任務。
這裏雖然也能夠寫直接添加爬取前1000頁的任務,可是考慮到實際狀況下任務可能會很是多,爲了讓任務隊列不溢出,開始能夠少添加一些。
接下來是worker
的編寫。
首先worker確定要有三個基礎部分:下載頁面、解析頁面、保存數據。除此以外,由於要爬取1000頁,因此還要添加新的任務來爬取剩下的990。
這裏能夠判斷當前頁碼+10是否大於1000,若是不大於的話把當前頁碼+10的網頁添加到新的任務隊列中。
def worker(queue, task, lock):
offset = (task["page"] - 1) * 50
print("downloading: page %d" % task["page"])
# 1. 下載頁面
resp = requests.get("http://tieba.baidu.com/f?kw="
"%E5%8C%97%E4%BA%AC%E7%A7%91%E6%8A%80%E5%A4%A7%E5%AD%A6&ie=utf-8&pn=" + str(offset))
soup = BeautifulSoup(resp.content, "html.parser")
# 2. 解析頁面
items = soup.find_all("a", {"class", "j_th_tit"})
docs = []
for index, item in enumerate(items):
docs.append({
"page": task["page"],
"index": index,
"title": item.get_text(),
"href": "http://tieba.baidu.com" + item.attrs["href"]
})
print(task["page"], index, item.get_text())
# 3. 保存數據
with lock:
save_docs(docs)
# 4. 添加新任務
if (task["page"] + 10) > 1000:
queue.put({"id": "NO"})
else:
queue.put({"id": "worker", "page": task["page"] + 10})
複製代碼
以上就是爬蟲的所有代碼,運行後能夠看到類型下面的結果。
經過以上代碼大概爬了4萬多條數據,以後的兩章咱們將把這些標題當作語料庫,而後對這些數據進行搜索。
網站可能會常常變化,若是上述爬蟲不能用的話,能夠爬取我保存下來的貼吧網頁:nladuo.cn/beike_tieba…。
分頁的格式相似於1.html、2.html、...、1000.html。