python爬虫初学实战——下载笔趣阁的书籍(附完整代码)

python爬虫初学入门实战(附完整代码)

——下载笔趣阁里的书籍并保存为txt文档(1)

实验环境

操作系统:windows 10
版本:python 3.8,并且已经安装requests库和bs4库
时间:2020-08-14

实验过程

http://www.biquge.info/92_92843/
以此链接的书籍为例子,进行书籍的下载

解析书本目录

在目录页面上点击ctrl+u进行源码分析,
分析出每一章节的url,并且获得每一章节的章节名,以便后面写入txt文档
源码分析
这里使用了beautiful soup来解析源码

def geturl_list(path, url):
    text = gethtml(url)
    soup = BeautifulSoup(text, "html.parser")
    #获得书名
    name = soup.find("h1").string
    #保存到txt文件
    fp = create_file(path,name)

    for i in soup.find_all('dd'):
        i_in = i.find("a")
        each_url = url + i_in.get("href")
        #章节名
        chapter_name = i.string
        #文章内容
        chapter = get_chapter(each_url)
        fp.write("\n\n"+chapter_name+"\n"+chapter)
        print(chapter_name+"下载成功")
    fp.close()

解析章节内容

进入其中一个章节,继续检查源码
文章源码
文章内容都放在“<!-go->” 到“<!-over->”之间,我们可以使用正则表达式匹配,提取出整个文章。使用re.S,不会对\n进行中断,保证文章的完整性。

re.findall('<!--go-->(.*?)<!--over-->',text,re.S) 

提取出的文章带有其他标签,稍微处理一下

chapter = re.sub('<br/>','\n',chapter)
chapter = re.sub('&nbsp;',' ',chapter)

文章就成功提取出来了

其他的完善

判断下载链接是否正确

使用正则去判断,如果找不到,则说明输入错误

def judge(url):
    c = re.findall("http://www\.biquge\.info/[0-9\_]+/",url)
    if(len(c) != 0):
        return c[0]
    else:
        print("请检查是否输入正确的下载链接,当前只能下载biquge.info下的书籍")
        return ""
判断路径并创建txt文件

先判断路径是否正确,如正确,创建以文章为名字的txt文件,不正确则重新输入

#创建txt文件并打开
def create_file(path,txtname):
    #文件路径处理
    if(path == ''): 
        full_path = txtname + ".txt"
    else: 
        full_path = path + "\\" + txtname + ".txt"
    try:
        fp = open(full_path, 'w', encoding='utf-8')
        return fp
    except:
        newpath = input("文件路径不正确,请重新输入文件路径")
        fp = create_file(newpath, txtname)
        return fp
基础伪装,章节读取失败的措施

首先是稍微进行伪装,更改请求头

myheaders={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36"}

其次问题是,访问频率过高,可能会导致访问失败。
所以可以增加随机数降低爬取的速度。最简单的方法,使用sleep函数。

time.sleep(random.randint(int(beg), int(end)))

实验效果

在beg和end都是0的情况下(即0延迟)进行的下载
下载
只有一章下载失败,下载失败的那一章经过5秒,重新下载
失败的
获得的txt效果图
在这里插入图片描述

完整代码

import requests
from bs4 import BeautifulSoup
import random
import time
import re

#@@@荒晓芜@@@

#可更改:希望延迟秒数范围beg<= ? <=end
beg = 0
end = 0

#请求头
myheaders = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36"}

    
#创建txt文件并打开
def create_file(path,txtname):
    #文件路径处理
    if(path == ''): 
        full_path = txtname + ".txt"
    else: 
        full_path = path + "\\" + txtname + ".txt"
    try:
        fp = open(full_path, 'w', encoding='utf-8')
        return fp
    except:
        newpath = input("文件路径不正确,请重新输入文件路径")
        fp = create_file(newpath,txtname)
        return fp
#获取页面
def gethtml(url, code="utf-8"):
    try:
        r = requests.get(url,headers=myheaders)
        r.raise_for_status()
        r.encoding = code
        time.sleep(random.randint(int(beg),int(end)))
        return r.text
    except:
        print("获取文章失败,5秒后将重新获取")
        time.sleep(5)
        return ""
#获取文章目录并开始写入txt
def geturl_list(path,url):
    text = gethtml(url)
    soup = BeautifulSoup(text, "html.parser")
    #获取书名
    name = soup.find("h1").string
    #获得该文件
    fp = create_file(path,name)

    for i in soup.find_all('dd'):
        i_in = i.find("a")
        each_url = url + i_in.get("href")
        #章节名
        chapter_name = i.string
        #文章内容
        chapter = get_chapter(each_url)
        fp.write("\n\n"+chapter_name+"\n"+chapter)
        print(chapter_name+"下载成功")
    fp.close()

#获得每个页面的文本
def get_chapter(each_url):
    text = gethtml(each_url)
    #重新获取
    while(text == ""):
        text = gethtml(each_url)
#.就是任意字符,*就是前面字符有任意多个,参数有re.S,不会对\n进行中断
    try:
        correct = re.findall('<!--go-->(.*?)<!--over-->',text,re.S) 
        chapter = correct[0]
        chapter = re.sub('<br/>','\n',chapter)
        chapter = re.sub('&nbsp;',' ',chapter)
        return chapter
    except:
        print("程序意外终止")
  
 #检查延迟秒数是否更改正确
def check_environment():
    if (beg < 0) or (beg > end):
        print("请检查程序延迟秒数是否配置正确,请退出程序重新配置")
        input("任意键退出")
        exit(0)
    else:
        print("============欢迎使用============")
     
#判断连接是否正确输入   
def judge(url):
    c = re.findall("http://www\.biquge\.info/[0-9\_]+/", url)
    if (len(c) != 0):
        return c[0]
    else:
        print("请检查是否输入正确的下载链接,当前只能下载biquge.info下的书籍")
        return ""

def main():
    check_environment()
    while(True):
        html_url = input("请输入要爬取的笔趣阁书籍")
        html_url = judge(html_url)
        if (html_url != ""):
            break
    path = input("保存的路径(可不填)")
    geturl_list(path, html_url)
    input("下载结束")
 
main()

写在最后

感谢小伙伴天天提供的一些思路~以及帮忙发现了一个致命的bug
不多说,我天最牛逼

同时也学习了正则表达式的使用
参考资料:
Python re.findall中正则表达式(.*?)和参数re.S使用

不足:
1.没有多线程增加爬取速度
2.未使用多ip,减少访问失败的问题
3.没有解决其他笔趣阁网站的爬取不兼容的问题

初学者,后续应该还会继续改进和完善qwq

新留言:大改了个框架,可以判断和爬不同的笔趣阁或者其他网站,只需要自己简单在函数里增加相应代码即可,这个就不贴源码了。
有兴趣的也可以和我互相学习交流
在这里插入图片描述

仅供个人学习,禁止用作其他用途

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值