文章目录
前言
想着趁热打铁,就又将上文的爬虫完善了一下,之前的一次只能爬一本书,完善了之后,可以连续爬一个页面的书。
话不多说,直接上源码
问题
报错
(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