欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

python 爬取全本免费小说网的小说

程序员文章站 2022-05-11 14:41:22
这几天朋友说想看电子书,但是只能在网上看,不能下载到本地后看,问我有啥办法?我找了好几个小说网址看了下,你只能直接在网上看,要下载txt要冲钱买会员,而且还不能在浏览器上直接复制粘贴。之后我就想到python的爬虫不就可以爬取后下载吗? 思路: 首先,选择网址:http://www.yznnw.co ......

  这几天朋友说想看电子书,但是只能在网上看,不能下载到本地后看,问我有啥办法?我找了好几个小说网址看了下,你只能直接在网上看,要下载txt要冲钱买会员,而且还不能在浏览器上直接复制粘贴。之后我就想到python的爬虫不就可以爬取后下载吗?

  思路:

  首先,选择网址:http://www.yznnw.com/files/article/html/1/1129/index.html 这个是全本免费小说网上《龙血战神》的网址:

  python 爬取全本免费小说网的小说

  f12,分析网页元素,可以看到,在此页的 .zjlist4 li a 下存放了所有章节的url,首先我们要获取这些url放在一个数组里。然后循环遍历下载

  python 爬取全本免费小说网的小说

  有了这些网址后开始分析具体的每一章:

  书名:

  python 爬取全本免费小说网的小说

  章节名:

  python 爬取全本免费小说网的小说

  内容:

  python 爬取全本免费小说网的小说

  下一章:

  python 爬取全本免费小说网的小说

  有了这些信息我们就可以开始爬取了(其实这里可以不爬取下一章的,主要我之前的思路是:下载小说的第一章后,返回小说的下一章,之后不断递归直到最后一页,这么做后下载速度慢,不能并发,还有就是一直递归占用资源大,一直请求服务器会断开连接,导致失败)

  所以我换成了这种思路:就是先获取所有的章节的网页连接,再用线程(你也可以用进程)开始下载,果然速度上升了好多,

  但是,仔细分析后发现,其实有些章节是作者的感言啥的,这些是不用下载的,而真正的章节的标题一定含有:****章*****,所以要用正则排除掉(这个要具体分析,不一定每个作者的感言标题都是这样的,不过直接使用此程序也可以,这样也没啥)

  python 爬取全本免费小说网的小说         python 爬取全本免费小说网的小说

  代码如下:

   

#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)))
    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/17/17455/index.html',
        'http://www.yznnw.com/files/article/html/45/45275/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

if __name__=="__main__":
    # # 主页
    base = 'http://www.yznnw.com'
    # 下载指定的书
    process_getallbook(base)

 

 

   如果要下载其他书的话,找到书的首页,添加到如下位置:

   找书的首页url,随便点开一章,删除后面的***.html,后回车,就是这本书的首页url。

  python 爬取全本免费小说网的小说

  python 爬取全本免费小说网的小说

 

  运行结果:

  python 爬取全本免费小说网的小说      python 爬取全本免费小说网的小说

 

  python 爬取全本免费小说网的小说

  python 爬取全本免费小说网的小说

 

     请求url失败的网页放在,log\req_error.txt中

  爬取失败的章节存放在这本书的目录下的error_url.txt中

  之后,你使用电子书生成器,生成就好