经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Python3 » 查看文章
爬虫实战:从网页到本地,如何轻松实现小说离线阅读
来源:cnblogs  作者:努力的小雨  时间:2024/3/19 9:41:41  对本文有异议

今天我们将继续进行爬虫实战,除了常规的网页数据抓取外,我们还将引入一个全新的下载功能。具体而言,我们的主要任务是爬取小说内容,并实现将其下载到本地的操作,以便后续能够进行离线阅读。

为了确保即使在功能逐渐增多的情况下也不至于使初学者感到困惑,我特意为你绘制了一张功能架构图,具体如下所示:

image

让我们开始深入解析今天的主角:小说网

小说解析

书单获取

在小说网的推荐列表中,我们可以选择解析其中的某一个推荐内容,而无需完全还原整个网站页面的显示效果,从而更加高效地获取我们需要的信息。

以下是一个示例代码,帮助你更好地理解:

  1. headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0'}
  2. req = Request("https://www.readnovel.com/",headers=headers)
  3. # 发出请求,获取html
  4. # 获取的html内容是字节,将其转化为字符串
  5. html = urlopen(req)
  6. html_text = bytes.decode(html.read())
  7. soup = bf(html_text,'html.parser')
  8. for li in soup.select('#new-book-list li'):
  9. a_tag = li.select_one('a[data-eid="qd_F24"]')
  10. p_tag = li.select_one('p')
  11. book = {
  12. 'href': a_tag['href'],
  13. 'title': a_tag.get('title'),
  14. 'content': p_tag.get_text()
  15. }
  16. print(book)

书籍简介

在通常情况下,我们会先查看书单,然后对书籍的大致内容进行了解,因此直接解析相关内容即可。以下是一个示例代码:

  1. headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0'}
  2. req = Request(f"https://www.readnovel.com{link}#Catalog",headers=headers)
  3. # 发出请求,获取html
  4. # 获取的html内容是字节,将其转化为字符串
  5. html = urlopen(req)
  6. html_text = bytes.decode(html.read())
  7. soup = bf(html_text,'html.parser')
  8. og_title = soup.find('meta', property='og:title')['content']
  9. og_description = soup.find('meta', property='og:description')['content']
  10. og_novel_author = soup.find('meta', property='og:novel:author')['content']
  11. og_novel_update_time = soup.find('meta', property='og:novel:update_time')['content']
  12. og_novel_status = soup.find('meta', property='og:novel:status')['content']
  13. og_novel_latest_chapter_name = soup.find('meta', property='og:novel:latest_chapter_name')['content']
  14. # 查找内容为"免费试读"的a标签
  15. div_tag = soup.find('div', id='j-catalogWrap')
  16. list_items = div_tag.find_all('li', attrs={'data-rid': True})
  17. for li in list_items:
  18. link_text = li.find('a').text
  19. if '第' in link_text:
  20. link_url = li.find('a')['href']
  21. link_obj = {'link_text':link_text,
  22. 'link_url':link_url}
  23. free_trial_link.append(link_obj)
  24. print(f"书名:{og_title}")
  25. print(f"简介:{og_description}")
  26. print(f"作者:{og_novel_author}")
  27. print(f"最近更新:{og_novel_update_time}")
  28. print(f"当前状态:{og_novel_status}")
  29. print(f"最近章节:{og_novel_latest_chapter_name}")

在解析过程中,我们发现除了获取书籍的大致内容外,还顺便解析了相关的书籍目录。将这些目录保存下来会方便我们以后进行试读操作,因为一旦对某本书感兴趣,我们接下来很可能会阅读一下。如果确实对书籍感兴趣,可能还会将其加入书单。为了避免在阅读时再次解析,我们在这里直接保存了这些目录信息。

免费试读

在这一步,我们的主要任务是解析章节的名称以及章节内容,并将它们打印出来,为后续封装成方法以进行下载或阅读做准备。这样做可以更好地组织和管理数据,提高代码的复用性和可维护性。下面是一个示例代码,展示了如何实现这一功能:

  1. headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0'}
  2. req = Request(f"https://www.readnovel.com{link}",headers=headers)
  3. # 发出请求,获取html
  4. # 获取的html内容是字节,将其转化为字符串
  5. html = urlopen(req)
  6. html_text = bytes.decode(html.read())
  7. soup = bf(html_text, 'html.parser')
  8. name = soup.find('h1',class_='j_chapterName')
  9. chapter = {
  10. 'name':name.get_text()
  11. }
  12. print(name.get_text())
  13. ywskythunderfont = soup.find('div', class_='ywskythunderfont')
  14. if ywskythunderfont:
  15. p_tags = ywskythunderfont.find_all('p')
  16. chapter['text'] = p_tags[0].get_text()
  17. print(chapter)

小说下载

当我们完成内容解析后,已经成功获取了小说的章节内容,接下来只需执行下载操作即可。对于下载操作的具体步骤,如果有遗忘的情况,我来帮忙大家进行回顾一下。

  1. file_name = 'a.txt'
  2. with open(file_name, 'w', encoding='utf-8') as file:
  3. file.write('尝试下载')
  4. print(f'文件 {file_name} 下载完成!')

包装一下

按照老规矩,以下是源代码示例。即使你懒得编写代码,也可以直接复制粘贴运行一下,然后自行琢磨其中的细节。这样能够更好地理解代码的运行逻辑和实现方式。

  1. # 导入urllib库的urlopen函数
  2. from urllib.request import urlopen,Request
  3. # 导入BeautifulSoup
  4. from bs4 import BeautifulSoup as bf
  5. from random import choice,sample
  6. from colorama import init
  7. from termcolor import colored
  8. from readchar import readkey
  9. FGS = ['green', 'yellow', 'blue', 'cyan', 'magenta', 'red']
  10. book_list = []
  11. free_trial_link = []
  12. headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0'}
  13. def get_hot_book():
  14. print(colored('开始搜索书单!',choice(FGS)))
  15. book_list.clear()
  16. req = Request("https://www.readnovel.com/",headers=headers)
  17. # 发出请求,获取html
  18. # 获取的html内容是字节,将其转化为字符串
  19. html = urlopen(req)
  20. html_text = bytes.decode(html.read())
  21. soup = bf(html_text,'html.parser')
  22. for li in soup.select('#new-book-list li'):
  23. a_tag = li.select_one('a[data-eid="qd_F24"]')
  24. p_tag = li.select_one('p')
  25. book = {
  26. 'href': a_tag['href'],
  27. 'title': a_tag.get('title'),
  28. 'content': p_tag.get_text()
  29. }
  30. book_list.append(book)
  31. def get_book_detail(link):
  32. global free_trial_link
  33. free_trial_link.clear()
  34. req = Request(f"https://www.readnovel.com{link}#Catalog",headers=headers)
  35. # 发出请求,获取html
  36. # 获取的html内容是字节,将其转化为字符串
  37. html = urlopen(req)
  38. html_text = bytes.decode(html.read())
  39. soup = bf(html_text,'html.parser')
  40. og_title = soup.find('meta', property='og:title')['content']
  41. og_description = soup.find('meta', property='og:description')['content']
  42. og_novel_author = soup.find('meta', property='og:novel:author')['content']
  43. og_novel_update_time = soup.find('meta', property='og:novel:update_time')['content']
  44. og_novel_status = soup.find('meta', property='og:novel:status')['content']
  45. og_novel_latest_chapter_name = soup.find('meta', property='og:novel:latest_chapter_name')['content']
  46. # 查找内容为"免费试读"的a标签
  47. div_tag = soup.find('div', id='j-catalogWrap')
  48. list_items = div_tag.find_all('li', attrs={'data-rid': True})
  49. for li in list_items:
  50. link_text = li.find('a').text
  51. if '第' in link_text:
  52. link_url = li.find('a')['href']
  53. link_obj = {'link_text':link_text,
  54. 'link_url':link_url}
  55. free_trial_link.append(link_obj)
  56. print(colored(f"书名:{og_title}",choice(FGS)))
  57. print(colored(f"简介:{og_description}",choice(FGS)))
  58. print(colored(f"作者:{og_novel_author}",choice(FGS)))
  59. print(colored(f"最近更新:{og_novel_update_time}",choice(FGS)))
  60. print(colored(f"当前状态:{og_novel_status}",choice(FGS)))
  61. print(colored(f"最近章节:{og_novel_latest_chapter_name}",choice(FGS)))
  62. def free_trial(link):
  63. req = Request(f"https://www.readnovel.com{link}",headers=headers)
  64. # 发出请求,获取html
  65. # 获取的html内容是字节,将其转化为字符串
  66. html = urlopen(req)
  67. html_text = bytes.decode(html.read())
  68. soup = bf(html_text, 'html.parser')
  69. name = soup.find('h1',class_='j_chapterName')
  70. chapter = {
  71. 'name':name.get_text()
  72. }
  73. print(colored(name.get_text(),choice(FGS)))
  74. ywskythunderfont = soup.find('div', class_='ywskythunderfont')
  75. if ywskythunderfont:
  76. p_tags = ywskythunderfont.find_all('p')
  77. chapter['text'] = p_tags[0].get_text()
  78. return chapter
  79. def download_chapter(chapter):
  80. file_name = chapter['name'] + '.txt'
  81. with open(file_name, 'w', encoding='utf-8') as file:
  82. file.write(chapter['text'].replace('\u3000\u3000', '\n'))
  83. print(colored(f'文件 {file_name} 下载完成!',choice(FGS)))
  84. def print_book():
  85. for i in range(0, len(book_list), 3):
  86. names = [f'{i + j}:{book_list[i + j]["title"]}' for j in range(3) if i + j < len(book_list)]
  87. print(colored('\t\t'.join(names),choice(FGS)))
  88. def read_book(page):
  89. if not free_trial_link:
  90. print(colored('未选择书单,无法阅读!',choice(FGS)))
  91. print(colored(free_trial(free_trial_link[page]['link_url'])['text'],choice(FGS)))
  92. get_hot_book()
  93. init() ## 命令行输出彩色文字
  94. print(colored('已搜索完毕!',choice(FGS)))
  95. print(colored('m:返回首页',choice(FGS)))
  96. print(colored('d:免费试读',choice(FGS)))
  97. print(colored('x:全部下载',choice(FGS)))
  98. print(colored('n:下一章节',choice(FGS)))
  99. print(colored('b:上一章节',choice(FGS)))
  100. print(colored('q:退出阅读',choice(FGS)))
  101. my_key = ['q','m','d','x','n','b']
  102. current = 0
  103. while True:
  104. while True:
  105. move = readkey()
  106. if move in my_key:
  107. break
  108. if move == 'q': ## 键盘‘Q’是退出
  109. break
  110. if move == 'd':
  111. read_book(current)
  112. if move == 'x': ## 这里只是演示为主,不循环下载所有数据了
  113. download_chapter(free_trial(free_trial_link[0]['link_url']))
  114. if move == 'b':
  115. current = current - 1
  116. if current < 0 :
  117. current = 0
  118. read_book(current)
  119. if move == 'n':
  120. current = current + 1
  121. if current > len(free_trial_link) :
  122. current = len(free_trial_link) - 1
  123. read_book(current)
  124. if move == 'm':
  125. print_book()
  126. current = 0
  127. num = int(input('请输入书单编号:=====>'))
  128. if num <= len(book_list):
  129. get_book_detail(book_list[num]['href'])

总结

今天在爬虫实战中,除了正常爬取网页数据外,我们还添加了一个下载功能,主要任务是爬取小说并将其下载到本地,以便离线阅读。为了避免迷糊,我为大家绘制了功能架构图。我们首先解析了小说网,包括获取书单、书籍简介和免费试读章节。然后针对每个功能编写了相应的代码,如根据书单获取书籍信息、获取书籍详细信息、免费试读章节解析和小说下载。最后,将这些功能封装成方法,方便调用和操作。通过这次实战,我们深入了解了爬虫的应用,为后续的项目提供了基础支持。

原文链接:https://www.cnblogs.com/guoxiaoyu/p/18069448

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号