1. 程式人生 > >爬蟲實踐---排行榜小說批量下載

爬蟲實踐---排行榜小說批量下載

timeout nis title name 十倍 == mini 好的 線程

一、目標

排行榜的地址:http://www.qu.la/paihangbang/

找到各類排行旁的的每一部小說的名字,和在該網站的鏈接。

二、觀察網頁的結構

技術分享

很容易就能發現,每一個分類都是包裹在:

<div class="index_toplist mright mbottom">

之中,
這種條理清晰的網站,大大方便了爬蟲的編寫。

在當前頁面找到所有小說的連接,並保存在列表即可。

三、列表去重的小技巧:

就算是不同類別的小說,也是會重復出現在排行榜的。
這樣無形之間就會浪費很多資源,尤其是在面對爬大量網頁的時候。
這裏只要一行代碼就能解決:

url_list = list(set(url_list))

這裏調用了一個list的構造函數set:這樣就能保證列表裏沒有重復的元素了。

四、代碼實現

模塊化,函數式編程是一個非常好的習慣,堅持把每一個獨立的功能都寫成函數,這樣會使代碼簡單又可復用。

1.網頁抓取頭:

import requests
from bs4 import BeautifulSoup

def get_html(url):
    try:
        r = requests.get(url,timeout=30)
        r.raise_for_status
        r.encoding=utf-8
        return r.text
    
except: return error!

2.獲取排行榜小說及其鏈接:

 爬取每一類型小說排行榜,
 按順序寫入文件,
 文件內容為 小說名字+小說鏈接
 將內容保存到列表
 並且返回一個裝滿url鏈接的列表
def get_content(url):

    url_list = []
    html = get_html(url)
    soup = BeautifulSoup(html,lxml)

    # 由於小說排版的原因,歷史類和完本類小說不在一個div裏
    category_list = soup.find_all(div,class_=
index_toplist mright mbottom) history_list = soup.find_all(div,class_=index_toplist mbottom) for cate in category_list: name = cate.find(div,class_=toptab).span.text with open(novel_list.csv,a+) as f: f.write(\n小說種類:{} \n.format(name)) book_list = cate.find(div,class_=topbooks).find_all(li) # 循環遍歷出每一個小說的的名字,以及鏈接 for book in book_list: link = http://www.qu.la/ + book.a[href] title = book.a[title] url_list.append(link) # 這裏使用a模式寫入,防止清空文件 with open(novel_list.csv,a) as f: f.write(小說名:{} \t 小說地址:{} \n.format(title,link)) for cate in history_list: name = cate.find(div,class_=toptab).span.text with open(novel_list.csv,a) as f: f.write(\n小說種類: {} \n.format(name)) book_list = cate.find(div,class_=topbooks).find_all(li) for book in book_list: link = http://www.qu.la/ + book.a[href] title = book.a[title] url_list.append(link) with open(novel_list.csv,a) as f: f.write(小說名:{} \t 小說地址:{} \n.format(title,link)) return url_list

3.獲取單本小說的所有章節鏈接:

  獲取該小說每個章節的url地址,並創建小說文件
 # 獲取單本小說的所有章節鏈接
def get_txt_url(url):

    url_list = []
    html = get_html(url)
    soup = BeautifulSoup(html,lxml)
    list_a = soup.find_all(dd)
    txt_name = soup.find(dt).text

    with open(C:/Users/Administrator/Desktop/小說/{}.txt.format(txt_name),a+) as f:
        f.write(小說標題:{} \n.format(txt_name))

    for url in list_a:
        url_list.append(http://www.qu.la/ + url.a[href])

    return url_list,txt_name

4.獲取單頁文章的內容並保存到本地

這裏有個小技巧:
從網上爬下來的文件很多時候都是帶著<br>之類的格式化標簽,
可以通過一個簡單的方法把它過濾掉:
html = get_html(url).replace(‘<br/>‘, ‘\n‘)
這裏單單過濾了一種標簽,並將其替換成‘\n’用於文章的換行,

def get_one_txt(url,txt_name):

    html = get_html(url).replace(<br/>,\n)
    soup = BeautifulSoup(html,lxml)
    try:
        txt = soup.find(div,id=content).text
        title = soup.find(h1).text

        with open(C:/Users/Administrator/Desktop/小說/{}.txt.format(txt.name),a) as f:
            f.write(title + \n\n)
            f.write(txt)
            print(當前小說:{}當前章節{}已經下載完畢.format(txt_name,title))
    except:
        print(ERROR!)

6.主函數

def get_all_txt(url_list):
    
    for url in url_list:
        # 遍歷獲取當前小說的所有章節的目錄,並且生成小說頭文件

        page_list,txt_name = get_txt_url(url)

def main():
    # 小說排行榜地址
    base_url = http://www.qu.la/paihangbang/
    # 獲取排行榜中所有小說的url鏈接
    url_list = get_content(base_url)
    # 除去重復的小說
    url_list = list(set(url_list))
    get_all_txt(url_list)

if __name__ == __main__:
    main()

7.輸出結果

技術分享技術分享

5.缺點:

本次爬蟲寫的這麽順利,更多的是因為爬的網站是沒有反爬蟲技術,以及文章分類清晰,結構優美。
但是,按照這篇文的思路去爬取小說,

大概計算了一下:
一篇文章需要:0.5s
一本小說(1000張左右):8.5分鐘
全部排行榜(60本): 8.5小時!


那麽,這種單線程的爬蟲,速度如何能提高呢?
自己寫個多線程模塊?

其實還有更好的方式:Scrapy框架
後面可將這裏的代碼重構一邊遍,
速度會幾十倍甚至幾百倍的提高了!
這其實也是多線程的威力!

 

爬蟲實踐---排行榜小說批量下載