python 爬取全本免費小說網的小說


  這幾天朋友說想看電子書,但是只能在網上看,不能下載到本地后看,問我有啥辦法?我找了好幾個小說網址看了下,你只能直接在網上看,要下載txt要沖錢買會員,而且還不能在瀏覽器上直接復制粘貼。之后我就想到python的爬蟲不就可以爬取后下載嗎?

  碼源下載:

    https://github.com/feiquan123/GetEBook/

  思路:

  首先,選擇網址:http://www.yznnw.com/files/article/html/1/1129/index.html 這個是全本免費小說網上《龍血戰神》的網址:

  

  F12,分析網頁元素,可以看到,在此頁的 .zjlist4 li a 下存放了所有章節的URL,首先我們要獲取這些url放在一個數組里。然后循環遍歷下載

  

  有了這些網址后開始分析具體的每一章:

  書名:

  

  章節名:

  

  內容:

  

  下一章:

  

  有了這些信息我們就可以開始爬取了(其實這里可以不爬取下一章的,主要我之前的思路是:下載小說的第一章后,返回小說的下一章,之后不斷遞歸直到最后一頁,這么做后下載速度慢,不能並發,還有就是一直遞歸占用資源大,一直請求服務器會斷開連接,導致失敗)

  所以我換成了這種思路:就是先獲取所有的章節的網頁連接,再用線程(你也可以用進程)開始下載,果然速度上升了好多,

  但是,仔細分析后發現,其實有些章節是作者的感言啥的,這些是不用下載的,而真正的章節的標題一定含有:****章*****,所以要用正則排除掉(這個要具體分析,不一定每個作者的感言標題都是這樣的,不過直接使用此程序也可以,這樣也沒啥)

           

  代碼如下:

   

#coding:utf-8
import urllib
import urllib.request
import multiprocessing
from bs4 import BeautifulSoup
import re
import os
import time

def get_pages(url):
    soup=""
    try:
        # 創建請求日志文件夾
        if 'Log' not in os.listdir('.'):
            os.mkdir(r".\Log")

        # 請求當前章節頁面  params為請求參數
        request = urllib.request.Request(url)
        response = urllib.request.urlopen(request)
        content = response.read()
        data = content.decode('gbk')
        # soup轉換
        soup = BeautifulSoup(data, "html.parser")

    except Exception as e:
        print(url+" 請求錯誤\n")
        with open(r".\Log\req_error.txt",'a',encoding='utf-8') as f:
            f.write(url+" 請求錯誤\n")
        f.close()
    return soup

# 通過章節的url下載內容,並返回下一頁的url
def get_ChartTxt(url,title,num):
    soup=get_pages(url)

    # 獲取章節名稱
    subtitle = soup.select('#htmltimu')[0].text
    # 判斷是否有感言
    if re.search(r'.*?章', subtitle) is  None:
        return
    # 獲取章節文本
    content = soup.select('#htmlContent')[0].text
    # 按照指定格式替換章節內容,運用正則表達式
    content = re.sub(r'\(.*?\)', '', content)
    content = re.sub(r'\r\n', '', content)
    content = re.sub(r'\n+', '\n', content)
    content = re.sub(r'<.*?>+', '', content)


    # 單獨寫入這一章
    try:
        with open(r'.\%s\%s %s.txt' % (title, num,subtitle), 'w', encoding='utf-8') as f:
            f.write(subtitle + content)
        f.close()
        print(num,subtitle, '下載成功')

    except Exception as e:
        print(subtitle, '下載失敗',url)
        errorPath='.\Error\%s'%(title)
        # 創建錯誤文件夾
        try :
            os.makedirs(errorPath)
        except Exception as e:
            pass
        #寫入錯誤文件
        with open("%s\error_url.txt"%(errorPath),'a',encoding='utf-8') as f:
            f.write(subtitle+"下載失敗 "+url+'\n')
        f.close()
    return


# 通過首頁獲得該小說的所有章節鏈接后下載這本書
def thread_getOneBook(indexUrl):
    soup = get_pages(indexUrl)
    # 獲取書名
    title = soup.select('#htmldhshuming')[0].text
    # 根據書名創建文件夾
    if title not in os.listdir('.'):
        os.mkdir(r".\%s" % (title))
        print(title, "文件夾創建成功———————————————————")

    # 加載此進程開始的時間
    print('下載 %s 的PID:%s...' % (title, os.getpid()))
    start = time.time()

    # 獲取這本書的所有章節
    charts_url = []
    # 提取出書的每章節不變的url
    indexUrl = re.sub(r'index.html', '', indexUrl)
    charts = soup.select(".zjlist4 li a")
    for i in charts:
        # print(j+i.attrs['href'])
        charts_url.append(indexUrl + i.attrs['href'])

    # 創建下載這本書的進程
    p = multiprocessing.Pool()
    #自己在下載的文件前加上編號,防止有的文章有上,中,下三卷導致有3個第一章
    num=1
    for i in charts_url:
        p.apply_async(get_ChartTxt, args=(i,title,num))
        num+=1
    print('等待 %s 所有的章節被加載......' % (title))
    p.close()
    p.join()
    end = time.time()
    print('下載 %s  完成,運行時間  %0.2f s.' % (title, (end - start)))
    print('開始生成 %s ................' %title )
    sort_allCharts(r'.',"%s.txt"%title)
    return

# 創建下載多本書書的進程
def process_getAllBook(base):
    # 輸入你要下載的書的首頁地址
    print('主程序的PID:%s' % os.getpid())
    book_indexUrl=[
        'http://www.yznnw.com/files/article/html/1/1129/index.html',
        'http://www.yznnw.com/files/article/html/29/29931/index.html',
        'http://www.yznnw.com/files/article/html/0/868/index.html'
    ]
    print("-------------------開始下載-------------------")
    p = []
    for i in book_indexUrl:
        p.append(multiprocessing.Process(target=thread_getOneBook, args=(i,)))
    print("等待所有的主進程加載完成........")
    for i in p:
        i.start()
    for i in p:
        i.join()
    print("-------------------全部下載完成-------------------")

    return

#合成一本書 def sort_allCharts(path,filename): lists
=os.listdir(path) # 對文件排序 # lists=sorted(lists,key=lambda i:int(re.match(r'(\d+)',i).group())) lists.sort(key=lambda i:int(re.match(r'(\d+)',i).group())) # 刪除舊的書 if os.path.exists(filename): os.remove(filename) print('舊的 %s 已經被刪除'%filename) # 創建新書 with open(r'.\%s'%(filename),'a',encoding='utf-8') as f: for i in lists: with open(r'%s\%s' % (path, i), 'r', encoding='utf-8') as temp: f.writelines(temp.readlines()) temp.close() f.close() print('新的 %s 已經被創建在當前目錄 %s '%(filename,os.path.abspath(filename))) return if __name__=="__main__": # # 主頁 base = 'http://www.yznnw.com' # 下載指定的書 process_getAllBook(base)
   #如果下載完出現卡的話,請單獨執行如下命令 # sort_allCharts(r
'.\龍血戰神',"龍血戰神.txt")

 

   如果要下載其他書的話,找到書的首頁,添加到如下位置:

   找書的首頁URL,隨便點開一章,刪除后面的***.html,后回車,就是這本書的首頁URL。

  

  

  運行結果:

        

 

  

  

 

     請求URL失敗的網頁放在,Log\req_error.txt中

  爬取失敗的章節存放在這本書的目錄下的error_url.txt中

  之后,你可以使用電子書生成器,生成就好,也可以在跟目錄下看到相應的總的小說:

  

  這個是我爬了3本書的結果,爬完后程序卡了,只能結束掉,單獨執行最后一條命令了。。。。。。。。

   手機端打開,目錄也正確

        

 

 

版權

作者:feiquan

出處:http://www.cnblogs.com/feiquan/

版權聲明:本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。

大家寫文都不容易,請尊重勞動成果~ 這里謝謝大家啦(*/ω\*)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM