Python小说爬虫实战:从环境配置到代码实现的完整解析

苏见山
苏见山
发布时间:2026-10-14| 3人浏览过
原创

本文详细记录了使用Python编写小说爬虫的全过程。文章从确定目标网址、分析页面结构入手,重点讲解了如何使用urllib.request获取网页内容,并通过设置Headers解决403 Forbidden错误。同时,针对常见的编码乱码问题,介绍了使用chardet库检测编码及手动指定GBK编码的方法,并结合socket.timeout处理网络超时异常,最终通过正则表达式提取章节内容并写入文件,提供了完整的代码实现参考。

Python小说爬虫实战:从环境配置到代码实现的完整解析

这是纪念我编写的第一个爬虫程序,前后历时三个白天完成。期间有两个上午因故暂停,但正是这些中断期间遇到的各种奇怪问题,促使我逐一解决并理清了基本操作。事实证明,对于这类技术,最有效的学习方式是在使用中学习,通过解决具体问题来掌握知识。只有按需索取,学习才更具针对性。

以下是对整个开发过程的简要记录。

--------------------------------------------------------------------------------

准备构思与目标确定

准备构思阶段

出于对Python的热爱,我希望尝试一些练手项目。然而,无论是阅读书籍还是直接参考他人的项目,最终往往沦为简单的复制粘贴。最实际的方法是亲自上手编写代码。虽然思路大体相同,但具体实现必须依靠自己完成。

以往通过复制粘贴获得的帮助,仅能告诉我大概的流程框架。

确定目标网址

目标网址是爬虫开发的关键。我理想中的爬虫应具备更高智能,只需输入关键词即可自动执行后续步骤,支持自定义范围,甚至能爬取整个互联网或百度内容。但目前的爬虫大多需要预先指定目标网址,通过该页面的内容执行规定操作。因此,在编写爬虫前,必须确定一个基准页面,这需要事先规划清楚程序的功能目标,例如是获取页面文本、相关链接还是其他数据。

本程序的目标是获取《剑来》小说,将各章节内容爬取并下载存储到本地文件中。

编程仅仅是实现目的的工具。

因此,核心重点在于分析具体需求。

获取小说目录页面是基础步骤。该页面包含各章节的链接、标题等信息,这正是我们所需的数据源。

有了各章节的链接,下一步就是进入每个链接以获取章节的具体内容。

因此,我们需要获取页面内容,并从中提取目标信息。

为此,我选择了使用urllib.request和re库。

前者用于获取网页内容,后者用于提取目标信息。

Headers设置与403错误解决

关于Headers的设置

如果直接使用urllib.request的urlopen()和read()方法,会报以下错误:


raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
HTTPError: HTTP Error 403: Forbidden

出现urllib2.HTTPError: HTTP Error 403: Forbidden错误,通常是因为网站禁止爬虫访问。解决方法是在请求中添加头信息,伪装成浏览器访问。


headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0'}
request = url_req.Request(url, headers=headers)
response = url_req.urlopen(request, data=None, timeout=3)
html = response.read().decode('GBK')

编码处理与超时异常捕获

注意:这里存在两个容易出问题的地方。 •编码:编码问题是使用爬虫时经常令人头疼的问题,由于网页源代码的编码格式不明确,我尝试了许久。

使用chardet库的detect()方法可以检测字节字符串的编码。因此,直接检测这里的html(先不解码),输出结果显示为GB2312。但在后续页面的爬取中,出现了部分字符编码异常的提示,因此我采取了范围更广的中文字符集GBK,从而解决了这个问题。 •设置超时范围:由于频繁获取网页内容,目标网站有时会出现无响应的情况。

(关于Python爬虫程序中途停止的问题,详见我在CSDN上的提问)

为此,我采取了捕获urlopen()的socket.timeout异常,并在出现异常时重新循环访问,直到成功获得目标页面。

正则表达式提取与文件写入

获取目标内容

这里使用的是正则表达式,即re模块。其使用过程并不复杂。

首先需要一个模式字符串。以re.I指定忽略大小写,编译后的对象拥有本身的匹配方法,这里使用的是findall(),返回一个包含所有结果的列表。可以及时返回输出其内容,进而选择合适的部分进行处理。

Python正则表达式

通过查看相关符号,这里使用(.+?)来实现匹配非贪婪模式(即尽可能少的匹配)下的任意无限字符,对其使用(),进而匹配括号内的模式。

文件写入

使用with open() as file:,进而可以处理文件。这种方式可以自动执行打开和关闭文件的操作,更为便捷安全。 with open(findall_title[0] + '.txt', 'w+', encoding='utf-8') as open_file:

•这里也要注意编码的问题,指定utf-8,会避免一些问题。 •这里使用w+模式,以追加方式写文件。

完整代码


# -*- coding: utf-8 -*-
"""
Created on Fri Aug 11 16:31:42 2017
@author: lart
"""

import urllib.request as url_req
import re, socket, time


def r_o_html(url):
  print('r_o_html begin')

  headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0'}

  request = url_req.Request(url, headers=headers)

  NET_STATUS = False
  while not NET_STATUS:
    try:
      response = url_req.urlopen(request, data=None, timeout=3)
      html = response.read().decode('GBK')
      print('NET_STATUS is good')
      print('r_o_html end')
      return html
    except socket.timeout:
      print('NET_STATUS is not good')
      NET_STATUS = False

def re_findall(re_string, operation, html):

  print('re_findall begin')
  pattern = re.compile(re_string, re.I)

  if operation == 'findall':
    result = pattern.findall(html)
  else:
    print('this operation is invalid')
    exit(-1)

  print('re_findall end')
  return result


if __name__ == '__main__':
  url_base = 'http://www.7kankan.la/book/1/'

  html = r_o_html(url_base)

  findall_title = re_findall(r'<title>(.+?)</title>', 'findall', html)

  findall_chapter = re_findall(r'<dd class="col-md-3"><a href=[\',"](.+?)[\',"] title=[\',"](.+?)[\',"]>', 'findall', html)

  with open(findall_title[0] + '.txt', 'w+', encoding='utf-8') as open_file:
    print('article文件打开', findall_chapter)
    for i in range(len(findall_chapter)):
      print('第' + str(i) + '章')

      open_file.write('\n\n\t' + findall_chapter[i][1] + '\n --------------------------------------------------------------------- \n')

      url_chapter = url_base + findall_chapter[i][0]

      html_chapter = r_o_html(url_chapter)

      findall_article = re_findall(r'&nbsp;&nbsp;&nbsp;&nbsp;(.+?)<br />', 'findall', html_chapter)

      findall_article_next = findall_chapter[i][0].replace('.html', '_2.html')

      url_nextchapter = url_base + findall_article_next

      html_nextchapter = r_o_html(url_nextchapter)

      if html_nextchapter:
        findall_article.extend(re_findall(r'&nbsp;&nbsp;&nbsp;&nbsp;(.+?)<br />', 'findall', html_nextchapter))

        for text in findall_article:
          open_file.write(text + '\n')

      time.sleep(1)

  print('文件写入完毕')

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。