爬虫 爬整个书库 自动翻页

前言

想着趁热打铁,就又将上文的爬虫完善了一下,之前的一次只能爬一本书,完善了之后,可以连续爬一个页面的书。
话不多说,直接上源码

问题

报错

(d:\Desktop\vscode\python.conda) d:\Desktop\vscode\python> d: && cd d:\Desktop\vscode\python && cmd /C "d:\Desktop\vscode\python.conda\python.exe c:\Users\ASUS.vscode\extensions\ms-python.python-2023.22.0\pythonFiles\lib\python\debugpy\adapter/…/…\debugpy\launcher 10537 – D:\Desktop\vscode\python\bookstore.py "

(d:\Desktop\vscode\python.conda) d:\Desktop\vscode\python>

原因:headers的问题

当时懒得又敲一遍headers,就复制粘贴了一下之前的
结果就报错了
爬不同的网站时,记得把Cookie和Host(如果用到的话)改一下
也可能没有某一个,注释掉就行了,我这里就注释掉了Host

header= {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0',
    'Cookie': 'hm=2ddbda39dfd88aa4b3ff183cae79e636',
    #'Host': '',
    'Connection': 'keep-alive'
}

找User-Agent和Cookie

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

完善

拼接网址的法子

1.rfind()方法

 nxturl = 'https://www.bige3.cc/book/'
    # rfind('/') 获取最后一个'/'字符的索引
    index = next_url_element.rfind('/') + 1
    nxturl += next_url_element[index:]

2.引进urllib.parse

import urllib.parse

#拼接网页地址的例子

url = 'https://www.bige3.cc/'
get_url = 'book/110697/'
next_url = urllib.parse.urljoin(url , get_url )
print(next_url)

根据书的最新章节完成自动翻页

在这里插入图片描述

# 在书的目录那里找到最新章节的url
#使用while()完成自动翻页

# 爬取终点
endurl=htt_tree.xpath('/html/body/div[4]/div[2]/div[2]/span[4]/a/@href')
endurl =  nxturl + endurl[0]

#url为准备下载的章节
while url != endurl:

#这样子会导致下不了最后一张,不过也只是个小问题,很好解决

之前的源码有漏洞,删去了
这是新的

说明(来自"python爬虫实战——小说爬取")

clean.py 用于实现数据清洗
items.py 用于定义需要爬取的变量
main.py 是整个项目的主函数
settings.py 用于定义请求头、请求间隔、代理IP等
spider.py 用于实现爬虫的基本逻辑

clean.py

# 数据清洗函数
import os


def clean_data(file_path, title,folder):
    """
    :param filename: 原文档名
    :param info: [bookTitle,
    """

    #print("\n==== 数据清洗开始 ====")

    # 新的文件名
    chapter_title ="精修版_"+title+".txt"
    #new_filename ="new"+filename
    #保存到文件夹里
    new_file_path = f"{folder}/{chapter_title}"

    # 打开两个文本文档
    f_old = open(file_path, 'r', encoding='utf-8')
    f_new = open(new_file_path, 'w', encoding='utf-8')
    lines = f_old.readlines()  # 按行读取原文档中的内容
    empty_cnt = 0  # 用于记录连续的空行数

    # 遍历原文档中的每行
    for line in lines:
        if line == '\n':        # 如果当前是空行
            empty_cnt += 1      # 连续空行数+1
            if empty_cnt >= 2:  # 如果连续空行数不少于2
                continue        # 直接读取下一行,当前空行不写入
        else:                   # 如果当前不是空行
            empty_cnt = 0       # 连续空行数清零
        if line.startswith("\u3000\u3000"):  # 如果有段首缩进
            line = line[2:]                  # 删除段首缩进
            f_new.write(line)                # 写入当前行
        elif line.startswith("第"):          # 如果当前行是章节标题
            f_new.write(line)                # 写入章节标题
            f_new.write("\r\n")              # 写入换行
            f_new.write("-" * 20)            # 写入20个'-'
            f_new.write("\n")                # 写入换行
        else:                                # 如果当前行是未缩进的普通段落
            f_new.write(line)                # 保持原样写入

    f_old.close()
    f_new.close()
    #AI说的:
    #使用try和except语句来尝试删除文件。如果在删除文件时发生错误,将捕获异常
    #并输出错误信息。如果文件不存在,输出提示信息。这样可以确保程序在删除文件
    #失败时不会中断,而是继续运行。
    try:
        os.remove(file_path)
    except:
        print("删除文件失败")
    #print(f"\n==== 数据清洗完成,新文件已保存到 {new_file_path} ====")

item.py

#拼接网页url
nxturl = 'https://www.bige3.cc/book/'

#书库
url='https://www.bige3.cc/xuanhuan/'

main.py

import requests
import item
from lxml import etree
import setting
import clean
import spider

def book_store():
        header=setting.headers
        url=item.url
        response = requests.get(url=url,headers=header)

        # 将网页内容按utf-8规范解码为文本形式
        text = response.content.decode('utf-8')

        # 将文本内容创建为可解析元素
        html = etree.HTML(text) # type: ignore
        ht=html.xpath('//div[@class="image"]/a/@href')


        #拼接网页地址的例子
        '''
        url = 'https://www.bige3.cc/'
        get_url = 'book/110697/'
        next_url = urllib.parse.urljoin(url , get_url )
        '''


        # 遍历所有书籍目录地址
        for htt in ht:
                spider.downbook(htt)


if __name__=='__main__':
        book_store()

setting.py


headers= {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0',
    'Cookie': 'hm=2ddbda39dfd88aa4b3ff183cae79e636',
    #'Host': '',
    'Connection': 'keep-alive'
}

spider.py

import os
import random
import time
import item
import clean
import requests
import setting
import urllib.parse
from lxml import etree

# 获取下一页链接的函数
def next_url(next_url_element):
    nxturl = 'https://www.bige3.cc/book/'
    # rfind('/') 获取最后一个'/'字符的索引
    index = next_url_element.rfind('/') + 1
    nxturl += next_url_element[index:]
    return nxturl



def downbook(htt):
    header=setting.headers
    shht=str(htt)
    print(shht)
    nxturl = item.nxturl
    # rfind('/') 获取最后一个'/'字符的索引
    #index = shht.rfind('/') + 1
    nxturl = urllib.parse.urljoin(nxturl,shht)
    print(nxturl)
    res = requests.get(url=nxturl,headers=header)
    t_res=res.content.decode('utf-8')
    #print(t_res)
    htt_tree = etree.HTML(t_res)
    
    #提取标题
    bookname = htt_tree.xpath('/html/body/div[4]/div[2]/h1/text()')[0]
    author =htt_tree.xpath('/html/body/div[4]/div[2]/div[2]/span[1]/text()')[0]
    update=htt_tree.xpath('/html/body/div[4]/div[2]/div[2]/span[3]/text()')[0]
    introduction=htt_tree.xpath('/html/body/div[4]/div[2]/div[4]/dl/dd/text()')[0]
    
    # 创建文件
    folder='./笔趣阁/' + bookname
    try:
            os.makedirs(folder)
    except Exception:
            print('文件已创建!')
    
    bookname(folder,[bookname,author,update,introduction])
    
    #第一章节
    htt_tr = htt_tree.xpath('/html/body/div[4]/div[2]/div[3]/a[2]/@href')
    htt_tr =  nxturl + htt_tr[0]
    print(htt_tr)
    
    file_name=down_book(htt_tr,htt_tree,folder)
    print("complete!")



def book_introduction(folder,info):
     # 书的介绍       
    fp = open(folder+'/'+info[0]+'_简介'+'.txt', 'w', encoding='utf-8')
    # 首先在新的文档中写入书籍信息
    fp.write('==  《' + info[1] + '》\r\n')  # 标题
    fp.write('==  ' + info[2] + '\r\n')     # 作者
    fp.write('==  ' + info[3] + '\r\n')     # 最后更新时间
    fp.write("=" * 10)
    fp.write('\r\n')
    fp.write('==  ' + info[4] + '\r\n')     # 简介
    fp.write("=" * 10)
    fp.write('\r\n')

    
   
def down_book(htt_tr,htt_tree,folder):
    header=setting.headers
    nxturl=item.nxturl
    maxPages = 767
    cnt = 0 

    # 记录上一章节的标题
    lastTitle = ''

    # 爬取起点
    url =  htt_tr

    # 爬取终点
    endurl =htt_tree.xpath('/html/body/div[4]/div[2]/div[2]/span[4]/a/@href')
    endurl =  nxturl + endurl[0]
    
    while url != endurl:
    #while True:
        cnt += 1  # 记录当前爬取的页面
        if cnt > maxPages:
                break  # 当爬取的页面数超过maxPages时停止

                #resp = requests.get(url, headers)
        try:
                resp = requests.get(url, header)  # 超时设置为10秒
        except:
                for i in range(4):  # 循环去请求网站
                    resp = requests.get(url, header, timeout=20)
                    if resp.status_code == 200:
                            break
        
        text = resp.content.decode('utf-8')
        html = etree.HTML(text)
        title = html.xpath('//*[@class="content"]/h1/text()')[0]
        contents = html.xpath('//*[@id="chaptercontent"]/text()')

        # 输出爬取进度信息
        print("cnt: {}, title = {}, url = {}".format(cnt, title, url))
        #print(contents)
        file_name = f"{folder}/{title}"
        #file_name=bookTitle+'.txt'
        #不写入第一行(是标题,重复了,不好看)
        i=1
        with open(file_name + '.txt', 'a', encoding='utf-8') as f_new:
            if title != lastTitle:  # 章节标题改变
                f_new.write(title) # 写入新的章节标题
                f_new.write('\n')
                lastTitle = title   # 更新章节标题
            for content in contents:
                if i==0:    
                    f_new.write(content)
                    f_new.write('\n\n')
                else:
                    i=0    
            f_new.close( )

        # 获取"下一页"按钮指向的链接
        next_url_element = html.xpath('//*[@class="Readpage pagedown"]/a[3]/@href')[0]
        url='https://www.bige3.cc/'+next_url_element
        clean.clean_data(file_name + '.txt',title, folder+"/")
        # 传入函数next_url得到下一页链接
        #url = next_url(next_url_element)
        
        book_sleep()
        
    return file_name
    
def book_sleep():
    sleepTime = random.randint(2, 6)  # 产生一个2~5之间的随机数
    time.sleep(sleepTime)             # 暂停2~5之间随机的秒数

收尾

一个悲伤的消息

在这里插入图片描述
这网站是不是被封了吖-_-

全部源码

已传到仓库,
我的github仓库
我的gitee仓库https://gitee.com/aa2255/smalltask

  • 14
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杀小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值