如何通过爬虫实战(六)高效爬取笔趣阁小说资源?

2026-04-11 09:461阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计2300个文字,预计阅读时间需要10分钟。

如何通过爬虫实战(六)高效爬取笔趣阁小说资源?

目录+爬虫实战(六):+ 爬虫技巧+网站分析+页面分析+源码分析+链接分析+编写代码+获取目录+访问目录+下载数据+搜索功能+ 总代码+爬虫实战

如何通过爬虫实战(六)高效爬取笔趣阁小说资源?

目录
  • 爬虫实战(六):爬笔趣阁
    • 一、 网站分析
      • 1、 页面分析
      • 2、 源码分析
      • 3、 链接分析
    • 二、 编写代码
      • 1、 获取目录
      • 2、 访问目录
      • 3、 下载数据
      • 4、 搜索功能
    • 三、 总代码

爬虫实战(六):爬笔趣阁 一、 网站分析 1、 页面分析

通过抓包分析可以得到,该网站为静态网站,所有信息都保存在页面源码中,可以直接从页面源码获取信息。

在目录中,发现其全部存储在一个dl的标签中

在搜索目录中,搜索内容存储在一个列表中,我们可以通过获取列表的长度来知道是否查找到了结果;如果没有搜索到结果,则不会将列表哦渲染出来,我们可以通过<div class="novelslistss"></div>来判断是否查找成功

2、 源码分析

通过分析源码,发现,目录包裹在<dl></dl>,内容包裹在一个<div id="content"></div>

3、 链接分析

# 通过几次搜索可以得到几个url # www.bqg.org/modules/article/search.php?searchkey=%BE%F8%CA%C0%CE%E4%C9%F1 # 绝世武神 # www.bqg.org/modules/article/search.php?searchkey=%BE%F8%CA%C0%CC%C6%C3%C5 # 绝世唐门 url = "www.bqg.org/modules/article/search.php?searchkey=%s" from urllib import parse print(parse.quote("绝世武神".encode("gbk"))) # 在多次尝试下,发现,其先是对文本内容进行gbk编码,再进行url编码 # 故,我们可以模拟搜索工具,来对内容进行精确的查找 name = input("请输入书名:") # 获取用户输入的书名 print(url % parse.quote(name.encode("gbk"))) # 得到url 二、 编写代码 1、 获取目录

# !/usr/bin/python3 # -*- coding: UTF-8 -*- __author__ = "A.L.Kun" __file__ = "biquge.py" __time__ = "2022/7/6 14:03" # 导入必要的模块 import requests, re # 发送请求,使用正则获取全部内容 from urllib import parse # 进行书名的编码 from fake_useragent import UserAgent # UA伪装 # 这次获取的是风起龙城的目录 url = "www.bqg.org/53_53985/" # 要爬取的url headers = { 'Accept': ' text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 'Accept-Encoding': ' gzip, deflate, br', 'Accept-Language': ' zh-CN,zh;q=0.9', 'Cache-Control': ' no-cache', 'Connection': ' keep-alive', 'Cookie': ' jieqiVisitId=article_articleviews%3D53982; jieqiVisitTime=jieqiArticlesearchTime%3D1657088500; clickbids=53982', 'Host': ' www.bqg.org', 'Pragma': ' no-cache', 'Referer': ' www.bqg.org/', 'sec-ch-ua': ' " Not A;Brand";v="99", "Chromium";v="102", "Google Chrome";v="102"', 'sec-ch-ua-mobile': ' ?0', 'sec-ch-ua-platform': ' "Windows"', 'Sec-Fetch-Dest': ' document', 'Sec-Fetch-Mode': ' navigate', 'Sec-Fetch-Site': ' same-origin', 'Sec-Fetch-User': ' ?1', 'Upgrade-Insecure-Requests': ' 1', 'user-agent': UserAgent().random } def get_menu(url): headers.update({'user-agent': UserAgent().random}) # 随机请求头 resp = requests.get(url, headers) # 发起请求 resp.encoding = resp.apparent_encoding # 要文件的编码应该为gbk temp = re.search("正文.*?</dl>", resp.text).group() # 进行剪切,去除开头那新更新的目录 lis = re.findall(r'<a href="(.*?)">(.*?)</a>', temp) # 使用正则获取到目录和对应目录的链接 url_de = [] chapters = [] for i in lis: url_de.append(f"{url}{i[0]}") chapters.append(i[1]) # print(url_de, chapters) return url_de, chapters # 返回结果 get_menu(url) 2、 访问目录

def get_content(url): headers.update({'user-agent': UserAgent().random}) # 随机请求头 resp = requests.get(url, headers) # 获取响应 resp.encoding = resp.apparent_encoding # 编码 content = re.search('<div id="content" name="content">(?P<content>.*?)</div>', resp.text, re.S).group("content") # 获取到内容 content = re.sub(r'<br.*?>', "\n", content) # 使用正则替换清洗数据 content = re.sub(r'&nbsp;', " ", content) # 使用正则替换清洗数据 return content # 返回结果 get_content("www.bqg.org/53_53985/38645272.html") # 测试使用 3、 下载数据

def save_data(url_): with open("./风起龙城.txt", "w", encoding="utf-8") as f: urls, menus = get_menu(url_) for index, url in enumerate(urls): f.write(f"==============={menus[index]}===============\n") print(f"正在下载:{menus[index]}") content = get_content(url) f.write(content + "\n") print(f"{menus[index]},下载完成") save_data("www.bqg.org/53_53985/") 4、 搜索功能

url = "www.bqg.org/modules/article/search.php?searchkey=%s" from lxml import etree from prettytable import PrettyTable def have_content(text): # 当查找到内容时,展示查找到的内容给用户选择 html = etree.HTML(text) li_s = html.xpath("//*[@id='main']/div[1]/li") table = PrettyTable(['序号', "类型", '书名', '作者']) lis_ = [] index = 0 for index, li in enumerate(li_s): print(index) type_ = li.xpath("./span[@class='s1']/text()")[0] name = li.xpath("./span[@class='s2']/a/text()")[0] url = li.xpath("./span[@class='s2']/a/@href")[0] lis_.append(url) author = li.xpath("./span[@class='s4']/text()")[0] table.add_row([index + 1, type_, name, author]) print(table) i = int(input("请输入要下载的序号:")) - 1 print(index) if 0 < i <= index: return lis_[i] print("请按要求输入哦!") sys.exit(0) def search(n): arg = parse.quote(n.encode("gbk")) headers.update({ 'User-Agent': UserAgent().random, "Cookie": f"jieqiVisitTime=jieqiArticlesearchTime%{int(time())}" }) # 随机请求头 print(headers) url_ = url % arg print(url_) resp = requests.get(url_, headers=headers) # 发起请求 print(resp) resp.encoding = resp.apparent_encoding # 设置当前编码 tet = resp.text # 获取内容 print(tet) if re.search("错误原因:对不起,没有搜索.*?文章!", tet): print("对不起,没有搜索到您要的文章!") return if re.search("错误原因:对不起,两次搜索.*?秒", tet): print("对不起,两次搜索的间隔时间不得少于30秒") return # 剩下的都是查到内容的 return have_content(tet) # 获取具体的下载名,并且把url返回 name = input("请输入要下载的小说:") search(name) 三、 总代码

# !/usr/bin/python3 # -*- coding: UTF-8 -*- __author__ = "A.L.Kun" __file__ = "biquge.py" __time__ = "2022/7/6 14:03" # 导入必要的模块 import requests, re, sys # 发送请求,使用正则获取全部内容 from urllib import parse # 进行书名的编码 from fake_useragent import UserAgent # UA伪装 from lxml import etree from prettytable import PrettyTable url = "www.bqg.org/modules/article/search.php?searchkey=%s" # 查找的url headers = { 'Accept': ' text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 'Accept-Encoding': ' gzip, deflate, br', 'Accept-Language': ' zh-CN,zh;q=0.9', 'Cache-Control': ' no-cache', 'Connection': ' keep-alive', 'Cookie': ' jieqiVisitId=article_articleviews%3D53982; jieqiVisitTime=jieqiArticlesearchTime%3D1657088500; clickbids=53982', 'Host': ' www.bqg.org', 'Pragma': ' no-cache', 'Referer': ' www.bqg.org/', 'sec-ch-ua': ' " Not A;Brand";v="99", "Chromium";v="102", "Google Chrome";v="102"', 'sec-ch-ua-mobile': ' ?0', 'sec-ch-ua-platform': ' "Windows"', 'Sec-Fetch-Dest': ' document', 'Sec-Fetch-Mode': ' navigate', 'Sec-Fetch-Site': ' same-origin', 'Sec-Fetch-User': ' ?1', 'Upgrade-Insecure-Requests': ' 1', 'user-agent': UserAgent().random } def have_content(text): # 当查找到内容时,展示查找到的内容给用户选择 html = etree.HTML(text) li_s = html.xpath("//*[@id='main']/div[1]/li") table = PrettyTable(['序号', "类型", '书名', '作者']) lis_ = [] index = 0 for index, li in enumerate(li_s): print(index) type_ = li.xpath("./span[@class='s1']/text()")[0] name = li.xpath("./span[@class='s2']/a/text()")[0] url = li.xpath("./span[@class='s2']/a/@href")[0] lis_.append(url) author = li.xpath("./span[@class='s4']/text()")[0] table.add_row([index + 1, type_, name, author]) print(table) i = int(input("请输入要下载的序号:")) - 1 print(index) if 0 < i <= index: return lis_[i] print("请按要求输入哦!") sys.exit(0) def search(n): arg = parse.quote(n.encode("gbk")) headers.update({ 'User-Agent': UserAgent().random, "Cookie": f"jieqiVisitTime=jieqiArticlesearchTime%{int(time())}" # cookie反爬 }) # 随机请求头 url_ = url % arg resp = requests.get(url_, headers=headers) # 发起请求 resp.encoding = resp.apparent_encoding # 设置当前编码 tet = resp.text # 获取内容 if re.search("错误原因:对不起,没有搜索.*?文章!", tet): print("对不起,没有搜索到您要的文章!") return if re.search("错误原因:对不起,两次搜索.*?秒", tet): print("对不起,两次搜索的间隔时间不得少于30秒") return # 剩下的都是查到内容的 return have_content(tet) # 获取具体的下载名,并且把url返回 def get_menu(url): headers.update({'user-agent': UserAgent().random}) # 随机请求头 resp = requests.get(url, headers) # 发起请求 resp.encoding = resp.apparent_encoding # 要文件的编码应该为gbk temp = re.search("正文.*?</dl>", resp.text).group() # 进行剪切,去除开头那新更新的目录 lis = re.findall(r'<a href="(.*?)">(.*?)</a>', temp) # 使用正则获取到目录和对应目录的链接 url_de = [] chapters = [] for i in lis: url_de.append(f"{url}{i[0]}") chapters.append(i[1]) # print(url_de, chapters) return url_de, chapters # 返回结果 def get_content(url): headers.update({'user-agent': UserAgent().random}) # 随机请求头 resp = requests.get(url, headers) # 获取响应 resp.encoding = resp.apparent_encoding # 编码 content = re.search('<div id="content" name="content">(?P<content>.*?)</div>', resp.text, re.S).group( "content") # 获取到内容 content = re.sub(r'<br.*?>', "\n", content) # 使用正则替换清洗数据 content = re.sub(r'&nbsp;', " ", content) # 使用正则替换清洗数据 return content # 返回结果 def save_data(url_, name): with open(f"./{name}.txt", "w", encoding="utf-8") as f: urls, menus = get_menu(url_) # 获取目录信息 for index, url in enumerate(urls): # 遍历链接 f.write(f"==============={menus[index]}===============\n") print(f"正在下载:{menus[index]}") content = get_content(url) # 获取详细信息 f.write(content + "\n") # 写入文件 print(f"{menus[index]},下载完成") # 提示信息 print("--------------------------") def main(): name = input("请输入要下载的小说名:") save_data(search(name), name) print("下载完成") if __name__ == "__main__": main()

本文共计2300个文字,预计阅读时间需要10分钟。

如何通过爬虫实战(六)高效爬取笔趣阁小说资源?

目录+爬虫实战(六):+ 爬虫技巧+网站分析+页面分析+源码分析+链接分析+编写代码+获取目录+访问目录+下载数据+搜索功能+ 总代码+爬虫实战

如何通过爬虫实战(六)高效爬取笔趣阁小说资源?

目录
  • 爬虫实战(六):爬笔趣阁
    • 一、 网站分析
      • 1、 页面分析
      • 2、 源码分析
      • 3、 链接分析
    • 二、 编写代码
      • 1、 获取目录
      • 2、 访问目录
      • 3、 下载数据
      • 4、 搜索功能
    • 三、 总代码

爬虫实战(六):爬笔趣阁 一、 网站分析 1、 页面分析

通过抓包分析可以得到,该网站为静态网站,所有信息都保存在页面源码中,可以直接从页面源码获取信息。

在目录中,发现其全部存储在一个dl的标签中

在搜索目录中,搜索内容存储在一个列表中,我们可以通过获取列表的长度来知道是否查找到了结果;如果没有搜索到结果,则不会将列表哦渲染出来,我们可以通过<div class="novelslistss"></div>来判断是否查找成功

2、 源码分析

通过分析源码,发现,目录包裹在<dl></dl>,内容包裹在一个<div id="content"></div>

3、 链接分析

# 通过几次搜索可以得到几个url # www.bqg.org/modules/article/search.php?searchkey=%BE%F8%CA%C0%CE%E4%C9%F1 # 绝世武神 # www.bqg.org/modules/article/search.php?searchkey=%BE%F8%CA%C0%CC%C6%C3%C5 # 绝世唐门 url = "www.bqg.org/modules/article/search.php?searchkey=%s" from urllib import parse print(parse.quote("绝世武神".encode("gbk"))) # 在多次尝试下,发现,其先是对文本内容进行gbk编码,再进行url编码 # 故,我们可以模拟搜索工具,来对内容进行精确的查找 name = input("请输入书名:") # 获取用户输入的书名 print(url % parse.quote(name.encode("gbk"))) # 得到url 二、 编写代码 1、 获取目录

# !/usr/bin/python3 # -*- coding: UTF-8 -*- __author__ = "A.L.Kun" __file__ = "biquge.py" __time__ = "2022/7/6 14:03" # 导入必要的模块 import requests, re # 发送请求,使用正则获取全部内容 from urllib import parse # 进行书名的编码 from fake_useragent import UserAgent # UA伪装 # 这次获取的是风起龙城的目录 url = "www.bqg.org/53_53985/" # 要爬取的url headers = { 'Accept': ' text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 'Accept-Encoding': ' gzip, deflate, br', 'Accept-Language': ' zh-CN,zh;q=0.9', 'Cache-Control': ' no-cache', 'Connection': ' keep-alive', 'Cookie': ' jieqiVisitId=article_articleviews%3D53982; jieqiVisitTime=jieqiArticlesearchTime%3D1657088500; clickbids=53982', 'Host': ' www.bqg.org', 'Pragma': ' no-cache', 'Referer': ' www.bqg.org/', 'sec-ch-ua': ' " Not A;Brand";v="99", "Chromium";v="102", "Google Chrome";v="102"', 'sec-ch-ua-mobile': ' ?0', 'sec-ch-ua-platform': ' "Windows"', 'Sec-Fetch-Dest': ' document', 'Sec-Fetch-Mode': ' navigate', 'Sec-Fetch-Site': ' same-origin', 'Sec-Fetch-User': ' ?1', 'Upgrade-Insecure-Requests': ' 1', 'user-agent': UserAgent().random } def get_menu(url): headers.update({'user-agent': UserAgent().random}) # 随机请求头 resp = requests.get(url, headers) # 发起请求 resp.encoding = resp.apparent_encoding # 要文件的编码应该为gbk temp = re.search("正文.*?</dl>", resp.text).group() # 进行剪切,去除开头那新更新的目录 lis = re.findall(r'<a href="(.*?)">(.*?)</a>', temp) # 使用正则获取到目录和对应目录的链接 url_de = [] chapters = [] for i in lis: url_de.append(f"{url}{i[0]}") chapters.append(i[1]) # print(url_de, chapters) return url_de, chapters # 返回结果 get_menu(url) 2、 访问目录

def get_content(url): headers.update({'user-agent': UserAgent().random}) # 随机请求头 resp = requests.get(url, headers) # 获取响应 resp.encoding = resp.apparent_encoding # 编码 content = re.search('<div id="content" name="content">(?P<content>.*?)</div>', resp.text, re.S).group("content") # 获取到内容 content = re.sub(r'<br.*?>', "\n", content) # 使用正则替换清洗数据 content = re.sub(r'&nbsp;', " ", content) # 使用正则替换清洗数据 return content # 返回结果 get_content("www.bqg.org/53_53985/38645272.html") # 测试使用 3、 下载数据

def save_data(url_): with open("./风起龙城.txt", "w", encoding="utf-8") as f: urls, menus = get_menu(url_) for index, url in enumerate(urls): f.write(f"==============={menus[index]}===============\n") print(f"正在下载:{menus[index]}") content = get_content(url) f.write(content + "\n") print(f"{menus[index]},下载完成") save_data("www.bqg.org/53_53985/") 4、 搜索功能

url = "www.bqg.org/modules/article/search.php?searchkey=%s" from lxml import etree from prettytable import PrettyTable def have_content(text): # 当查找到内容时,展示查找到的内容给用户选择 html = etree.HTML(text) li_s = html.xpath("//*[@id='main']/div[1]/li") table = PrettyTable(['序号', "类型", '书名', '作者']) lis_ = [] index = 0 for index, li in enumerate(li_s): print(index) type_ = li.xpath("./span[@class='s1']/text()")[0] name = li.xpath("./span[@class='s2']/a/text()")[0] url = li.xpath("./span[@class='s2']/a/@href")[0] lis_.append(url) author = li.xpath("./span[@class='s4']/text()")[0] table.add_row([index + 1, type_, name, author]) print(table) i = int(input("请输入要下载的序号:")) - 1 print(index) if 0 < i <= index: return lis_[i] print("请按要求输入哦!") sys.exit(0) def search(n): arg = parse.quote(n.encode("gbk")) headers.update({ 'User-Agent': UserAgent().random, "Cookie": f"jieqiVisitTime=jieqiArticlesearchTime%{int(time())}" }) # 随机请求头 print(headers) url_ = url % arg print(url_) resp = requests.get(url_, headers=headers) # 发起请求 print(resp) resp.encoding = resp.apparent_encoding # 设置当前编码 tet = resp.text # 获取内容 print(tet) if re.search("错误原因:对不起,没有搜索.*?文章!", tet): print("对不起,没有搜索到您要的文章!") return if re.search("错误原因:对不起,两次搜索.*?秒", tet): print("对不起,两次搜索的间隔时间不得少于30秒") return # 剩下的都是查到内容的 return have_content(tet) # 获取具体的下载名,并且把url返回 name = input("请输入要下载的小说:") search(name) 三、 总代码

# !/usr/bin/python3 # -*- coding: UTF-8 -*- __author__ = "A.L.Kun" __file__ = "biquge.py" __time__ = "2022/7/6 14:03" # 导入必要的模块 import requests, re, sys # 发送请求,使用正则获取全部内容 from urllib import parse # 进行书名的编码 from fake_useragent import UserAgent # UA伪装 from lxml import etree from prettytable import PrettyTable url = "www.bqg.org/modules/article/search.php?searchkey=%s" # 查找的url headers = { 'Accept': ' text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 'Accept-Encoding': ' gzip, deflate, br', 'Accept-Language': ' zh-CN,zh;q=0.9', 'Cache-Control': ' no-cache', 'Connection': ' keep-alive', 'Cookie': ' jieqiVisitId=article_articleviews%3D53982; jieqiVisitTime=jieqiArticlesearchTime%3D1657088500; clickbids=53982', 'Host': ' www.bqg.org', 'Pragma': ' no-cache', 'Referer': ' www.bqg.org/', 'sec-ch-ua': ' " Not A;Brand";v="99", "Chromium";v="102", "Google Chrome";v="102"', 'sec-ch-ua-mobile': ' ?0', 'sec-ch-ua-platform': ' "Windows"', 'Sec-Fetch-Dest': ' document', 'Sec-Fetch-Mode': ' navigate', 'Sec-Fetch-Site': ' same-origin', 'Sec-Fetch-User': ' ?1', 'Upgrade-Insecure-Requests': ' 1', 'user-agent': UserAgent().random } def have_content(text): # 当查找到内容时,展示查找到的内容给用户选择 html = etree.HTML(text) li_s = html.xpath("//*[@id='main']/div[1]/li") table = PrettyTable(['序号', "类型", '书名', '作者']) lis_ = [] index = 0 for index, li in enumerate(li_s): print(index) type_ = li.xpath("./span[@class='s1']/text()")[0] name = li.xpath("./span[@class='s2']/a/text()")[0] url = li.xpath("./span[@class='s2']/a/@href")[0] lis_.append(url) author = li.xpath("./span[@class='s4']/text()")[0] table.add_row([index + 1, type_, name, author]) print(table) i = int(input("请输入要下载的序号:")) - 1 print(index) if 0 < i <= index: return lis_[i] print("请按要求输入哦!") sys.exit(0) def search(n): arg = parse.quote(n.encode("gbk")) headers.update({ 'User-Agent': UserAgent().random, "Cookie": f"jieqiVisitTime=jieqiArticlesearchTime%{int(time())}" # cookie反爬 }) # 随机请求头 url_ = url % arg resp = requests.get(url_, headers=headers) # 发起请求 resp.encoding = resp.apparent_encoding # 设置当前编码 tet = resp.text # 获取内容 if re.search("错误原因:对不起,没有搜索.*?文章!", tet): print("对不起,没有搜索到您要的文章!") return if re.search("错误原因:对不起,两次搜索.*?秒", tet): print("对不起,两次搜索的间隔时间不得少于30秒") return # 剩下的都是查到内容的 return have_content(tet) # 获取具体的下载名,并且把url返回 def get_menu(url): headers.update({'user-agent': UserAgent().random}) # 随机请求头 resp = requests.get(url, headers) # 发起请求 resp.encoding = resp.apparent_encoding # 要文件的编码应该为gbk temp = re.search("正文.*?</dl>", resp.text).group() # 进行剪切,去除开头那新更新的目录 lis = re.findall(r'<a href="(.*?)">(.*?)</a>', temp) # 使用正则获取到目录和对应目录的链接 url_de = [] chapters = [] for i in lis: url_de.append(f"{url}{i[0]}") chapters.append(i[1]) # print(url_de, chapters) return url_de, chapters # 返回结果 def get_content(url): headers.update({'user-agent': UserAgent().random}) # 随机请求头 resp = requests.get(url, headers) # 获取响应 resp.encoding = resp.apparent_encoding # 编码 content = re.search('<div id="content" name="content">(?P<content>.*?)</div>', resp.text, re.S).group( "content") # 获取到内容 content = re.sub(r'<br.*?>', "\n", content) # 使用正则替换清洗数据 content = re.sub(r'&nbsp;', " ", content) # 使用正则替换清洗数据 return content # 返回结果 def save_data(url_, name): with open(f"./{name}.txt", "w", encoding="utf-8") as f: urls, menus = get_menu(url_) # 获取目录信息 for index, url in enumerate(urls): # 遍历链接 f.write(f"==============={menus[index]}===============\n") print(f"正在下载:{menus[index]}") content = get_content(url) # 获取详细信息 f.write(content + "\n") # 写入文件 print(f"{menus[index]},下载完成") # 提示信息 print("--------------------------") def main(): name = input("请输入要下载的小说名:") save_data(search(name), name) print("下载完成") if __name__ == "__main__": main()