1. 程式人生 > >那些年,我爬過的北科(九)——搜尋案例之爬蟲編寫

那些年,我爬過的北科(九)——搜尋案例之爬蟲編寫

案例介紹

從本章開始,我們將要開始進入最後的案例實踐篇。

在爬取資料之後,我們一般會怎麼用資料呢?一般來講,我們可能會做一個搜尋引擎,比如說我們爬了新聞,可能會做一個新聞的搜尋;爬取了小說可能做一個小說的搜尋。

本案例將要爬取北科貼吧的帖子資料,並在此基礎上構建一個簡單的搜尋功能。

百度貼吧分析

這裡我們首先開啟北京科技大學的百度貼吧:tieba.baidu.com/f?kw=北京科技大學

我們的目標是關注帖子的標題名稱,比如這個:“北郵人下載需要流量嗎”“請問一下學長學姐,全國大學生數學競賽初賽全國一等獎在咱們學校”

還有就是我們肯定不能只爬取一頁的資訊,這裡我們將要爬取前1000頁的資訊。

頁面分析

首先我們開啟Chrome開發者工具看一下列表如何解析。

這裡我們選中一個標題名稱後,可以直接看到一個a標籤,它的class為j_th_tit

所以使用以下程式碼就可以打印出所有的標題來。

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)
複製程式碼

分頁分析

頁面分析完了之後就可以分析一下分頁了,我們把小箭頭晃到底部分頁的位置。

可以發現分頁對應的網址主要是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的編寫。

首先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。