前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【Python爬虫实战入门】:笔趣阁小说爬取,一篇教你爬虫入门

【Python爬虫实战入门】:笔趣阁小说爬取,一篇教你爬虫入门

作者头像
爱喝兽奶的熊孩子
发布于 2024-08-06 01:16:47
发布于 2024-08-06 01:16:47
65400
代码可运行
举报
文章被收录于专栏:C语言基础C语言基础
运行总次数:0
代码可运行
🚀一、爬虫需求及其目标网站

目标网站https://www.3bqg.cc/book/12257/ 需求:爬取小说章节名称及其对应的小说内容,并保存到本地,要求以章节名作为文件名。

🔥二、所需的第三方库及简介

requests

简介requests模块 官方文档https://requests.readthedocs.io/projects/cn/zh-cn/latest/

requests 是 Python 编程语言中一个常用的第三方库,它可以帮助我们向 HTTP 服务器发送各种类型的请求,并处理响应。

  • 向 Web 服务器发送 GET、POST 等请求方法;
  • 在请求中添加自定义标头(headers)、URL 参数、请求体等;
  • 自动处理 cookies;
  • 返回响应内容,并对其进行解码;
  • 处理重定向和跳转等操作;
  • 检查响应状态码以及请求所消耗的时间等信息。

BeautifulSoup

简介Beautiful Soup(bs4)

Beautiful Soup 是一个 可以从 HTML 或 XML 文件中提取数据的 Python 库。它能用你喜欢的解析器和习惯的方式实现 文档树的导航、查找、和修改。

❤️三、爬虫案例实战

打开网站

F12进入开发者模式,点击网络,刷新页面后点击搜索框,输入章节名称,就可以找到所需要的数据位于哪个数据包。

点击标头,获取请求网址以及请求方法。请求网址就是我们爬虫所需要的目标网址了,请求可以看到等会儿我们需要用get方法发送请求。

爬虫函数框架

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 导入模块
import requests
from bs4 import BeautifulSoup
import os
import re

# 获取网页源码
def get_html():
    pass
# 解析数据
def parse_html():
    pass
# 保存数据
def save_data():
    pass
# 主函数
def main():
    pass

第一步:获取网页源码

获取请求头信息User-Agent,HTTP请求头的一部分,用于标识发送HTTP请求的用户代理(User Agent)。它通常包含了软件应用程序或用户使用的操作系统、浏览器、版本号等信息,让服务器能够识别客户端的类型。

  • Mozilla/5.0 表示该软件是Mozilla兼容的,版本号为5.0。
  • (Windows NT 10.0; Win64; x64) 表示操作系统是Windows 10的64位版本。
  • AppleWebKit/537.36 表示浏览器使用的渲染引擎版本。
  • (KHTML, like Gecko) 是针对KHTML(KHTML是Konqueror的渲染引擎)的补充信息,表示浏览器的内核类似于Gecko。
  • Chrome/91.0.4472.124 表示浏览器和其版本号。
  • Safari/537.36 表示浏览器基于Safari的版本号。

User-Agent的信息有助于网站提供适当的内容或功能给不同类型的客户端,也可以用于统计分析和安全审计等目的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 请求头信息
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
}
# 获取网页源码
def get_html(url):
    res = requests.get(url, headers=headers)
    print(res.text)
# 主函数
def main():
    url = 'https://www.3bqg.cc/book/12257/'
    get_html(url)
main()

第二步:数据解析 接下来我们就可以利用bs4进行数据筛选,提取。 在获取到网页源码后就可以不需要打印了,可以直接将网页源码作为返回值给返回出来,在parse_html函数中进行数据解析,提取。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 导入模块
# 获取网页源码
def get_html(url):
    res = requests.get(url, headers=headers)
    return res.text
# 解析数据
def parse_html(html):
    soup = BeautifulSoup(html, 'lxml')  # 实例化

可以看到,所有的章节都在dd标签里面,而所有的dd标签又在div标签里面,所以我们可以直接通过id或者class属性对div标签进行精准定位,在通过div标签找到所有包含了章节名的dd标签。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 解析数据
def parse_html(html):
    soup = BeautifulSoup(html, 'lxml')
    # 解析目录及其小说详情页
    tag_div = soup.find('div', class_='listmain')
    tag_dd = tag_div.find_all('dd')
    for tag in tag_dd:
        print(tag)

打印出来之后可以看到,章节名就在dd标签里面的a标签里面,只需要通过循环dd标签,在dd标签里面一个个找a标签就可以了,然后通过string属性直接获取a标签里面的文本内容。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 导入模块
import requests
from bs4 import BeautifulSoup
import os
import re
# 请求头信息
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
}
# 获取网页源码
def get_html(url):
    res = requests.get(url, headers=headers)
    return res.text
# 解析数据
def parse_html(html):
    soup = BeautifulSoup(html, 'lxml')
    # 解析目录及其小说详情页
    tag_div = soup.find('div', class_='listmain')
    tag_dd = tag_div.find_all('dd')
    for tag in tag_dd:
        tag_a = tag.find('a')
        title = tag_a.string
        print(title)
# 保存数据
def save_data():
    pass
# 主函数
def main():
    url = 'https://www.3bqg.cc/book/12257/'
    html = get_html(url)
    parse_html(html)
main()

注意:在获取章节名称是有一个 <<—展开全部章节—>> 是需要去掉的,我们可以直接在循环的时候加一个判断,如果获取到的文本内容等于 <<—展开全部章节—>>就直接跳过本次循环。

另外要注意的一点就是有些章节名上会有一些特殊符号,比如 ?、*、:、"、\、/、| 等等,这些特殊符号都是无法作为文件名的,所以这里最好提前处理一下,比如用正则表达式将这些特殊字符给替换掉。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 解析数据
def parse_html(html):
    soup = BeautifulSoup(html, 'lxml')
    # 解析目录及其小说详情页
    tag_div = soup.find('div', class_='listmain')
    tag_dd = tag_div.find_all('dd')
    for tag in tag_dd:
        tag_a = tag.find('a')
        title = tag_a.string
        if title == '<<---展开全部章节--->>':
            continue
        title = re.sub(r'[?*:"\/|]', '', title)  # 用正则表达式替换特殊字符
        print(title)

章节名称获取下来之后,接下来就是章节对应的文章内容,仔细观察后可以发现,a标签里面的href属性里面的值就是小说内容的链接的一部分,所以我们想要获取小说内容链接就只需要获取a标签里面的href属性值,在进行拼接一下就可以获取完整链接。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 解析数据
def parse_html(html):
    soup = BeautifulSoup(html, 'lxml')
    # 解析目录及其小说详情页
    tag_div = soup.find('div', class_='listmain')
    tag_dd = tag_div.find_all('dd')
    for tag in tag_dd:
        tag_a = tag.find('a')
        title = tag_a.string
        if title == '<<---展开全部章节--->>':
            continue
        href = 'https://www.3bqg.cc' + tag_a.get('href')
        print(title, href)

最后就只需要对面一个链接发送一个请求,获取源码,提取小说文本内容就可以了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
href = 'https://www.3bqg.cc' + tag_a.get('href')
html = get_html(href)
soup1 = BeautifulSoup(html, 'lxml')
tag_div1 = soup1.find('div', id='chaptercontent')
print(tag_div1)

这里获取文本内容不可以直接通过br标签获取,因为这里有些br标签里面是空的,直接通过string属性去获取文本内容会导致报错。这里可以通过stripped_strings, stripped_strings是一个生成器,用于获取去除了首尾空白字符的所有子孙节点的文本内容。将他强转成列表,在通过join方法连接即可得到小说文本内容。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
href = 'https://www.3bqg.cc' + tag_a.get('href')
html = get_html(href)
soup1 = BeautifulSoup(html, 'lxml')
tag_div1 = soup1.find('div', id='chaptercontent')
data = list(tag_div1.stripped_strings)
concent = '\n   '.join(data)
print(concent)

第三步:数据保存 利用Python的os模块中的mkdir来创建文件夹,注意,在创建文件夹之前一定要判断文件夹是否存在,如果存在就无法创建。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 保存数据
def save_data(title, concent):
    path = '末日乐园'
    if not os.path.exists(path):
        os.mkdir(path)
    with open(f'{path}/{title}.txt', 'w', encoding='utf-8') as f:
        f.write(concent)
    print(f'{title}章节爬取成功--------------------------------------')
🌈四、爬虫完整代码
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 导入模块
import requests
from bs4 import BeautifulSoup
import os
import re
# 请求头信息
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
}
# 获取网页源码
def get_html(url):
    res = requests.get(url, headers=headers)
    return res.text
# 保存数据
def save_data(title, concent):
    path = '末日乐园'
    if not os.path.exists(path):
        os.mkdir(path)
    with open(f'{path}/{title}.txt', 'w', encoding='utf-8') as f:
        f.write(concent)
    print(f'{title}章节爬取成功--------------------------------------')
# 解析数据
def parse_html(html):
    soup = BeautifulSoup(html, 'lxml')
    # 解析目录及其小说详情页
    tag_div = soup.find('div', class_='listmain')
    tag_dd = tag_div.find_all('dd')
    for tag in tag_dd:
        tag_a = tag.find('a')
        title = tag_a.string
        if title == '<<---展开全部章节--->>':
            continue
        title = re.sub(r'[?*:"\/|]', '', title)
        href = 'https://www.3bqg.cc' + tag_a.get('href')
        html = get_html(href)
        soup1 = BeautifulSoup(html, 'lxml')
        tag_div1 = soup1.find('div', id='chaptercontent')
        data = list(tag_div1.stripped_strings)
        concent = '\n   '.join(data)
        save_data(title, concent)
# 主函数
def main():
    url = 'https://www.3bqg.cc/book/12257/'
    html = get_html(url)
    parse_html(html)
main()
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-07-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
解锁动态规划的奥秘:从零到精通的创新思维解析(5)
小编在前几日分享了关于动态规划的题目,今天我们继续沿着之前的思路,深入探索动态规划的魅力。今天要讲解的依旧是路径问题,与前面讲过的题目在解法上有一定相似之处。如果大家对这类题目的解法还不太熟悉,可以回顾一下之前的文章,巩固基础。话不多说,让我们进入今天的代码之旅!
用户11295429
2025/01/10
730
解锁动态规划的奥秘:从零到精通的创新思维解析(5)
解锁动态规划的奥秘:从零到精通的创新思维解析(3)
小编在前几日书写了关于动态规划习题的博客(PS:其实这些都是我的存稿,我已经好久没写博客了截止到现在,确实摆烂),今天各位继续跟着小编的步伐,走进动态规划的世界,接下来我们将会·讲述一个比较新的动态规划问题:路径问题。
用户11295429
2025/01/03
500
解锁动态规划的奥秘:从零到精通的创新思维解析(3)
解锁动态规划的奥秘:从零到精通的创新思维解析(9)
小编在前几日写了关于动态规划中的多状态dp的问题,此时小编将会讲述一个动态规划我们常常会遇到的一类问题——股票问题,股票问题就类似小编上一篇所讲述的粉刷房子的问题,可以通过一个二维的dp表来代替多个一维的dp表。买卖股票算是一个很经典的问题了,下面小编简单介绍一下买卖股票问题。
用户11295429
2025/04/18
390
解锁动态规划的奥秘:从零到精通的创新思维解析(9)
解锁动态规划的奥秘:从零到精通的创新思维解析(8)
小编在前几日讲述了关于动态规划的习题,下面小编继续跟着上次的步伐,继续进入多状态dp问题的讲解(但是今天这个题目不需要多状态),今天由于小编的精力有限,所以我就仅仅先讲述一个题目,等小编过几天精力恢复过来就给各位正常的每日两题的讲解。
用户11295429
2025/04/16
970
解锁动态规划的奥秘:从零到精通的创新思维解析(8)
解锁动态规划的奥秘:从零到精通的创新思维解析(6)
在动态规划的众多问题中,多状态DP问题是一个非常重要的类别。它的难点在于如何设计合适的状态表示和转移方程,从而高效地解决问题。
用户11295429
2025/01/19
880
解锁动态规划的奥秘:从零到精通的创新思维解析(6)
解锁动态规划的奥秘:从零到精通的创新思维解析(10)
前几天,我写了一篇关于动态规划的文章,今天继续为大家带来一些动态规划相关的习题解析。本次分享的两道题依然围绕“股票”问题展开,不过相比之前的题目,难度有所提升。希望能为大家的学习提供帮助!
用户11295429
2025/05/02
750
解锁动态规划的奥秘:从零到精通的创新思维解析(10)
解锁动态规划的奥秘:从零到精通的创新思维解析(2)
小编在前几日讲述了关于动态规划的题目,今天小编继续进行动态规划相关题目的书写,动态规划的题目相较于小编之前讲述的习题难度是蛮大的,希望各位可以克服困难,最终掌握动态规划的题,下面就进入本文的讲题环节。
用户11295429
2025/01/03
740
解锁动态规划的奥秘:从零到精通的创新思维解析(2)
解锁动态规划的奥秘:从零到精通的创新思维解析(7)
在前几天的文章中,小编为大家讲解了动态规划中多状态 DP 问题的相关内容。今天,我们将延续上篇文章的主题,继续深入剖析多状态 DP 的解题思路和技巧。快系好安全带,准备好,我们的算法世界之旅再次启程!
用户11295429
2025/02/04
720
解锁动态规划的奥秘:从零到精通的创新思维解析(7)
【动态规划篇】- 路径问题
因为到达[1][1]这个位置共有一种路径,所以我们仅需将dp[1][0]或者dp[0][1]位置初始化为1,其余位置初始化为0即可。
_孙同学
2025/03/30
880
【动态规划篇】- 路径问题
解锁动态规划的奥秘:从零到精通的创新思维解析(1)
在算法的世界里,动态规划(Dynamic Programming, DP)以其强大的问题分解与优化能力,占据着极为重要的地位。无论是在学术研究还是实际应用中,它都广泛用于解决最优子结构和重叠子问题的复杂场景。从路径规划到资源分配,从游戏策略到数据压缩,动态规划的方法论为我们提供了一把破解复杂问题的利器。然而,初学者往往会被它的理论抽象和实现细节所困扰。本文将通过一道经典动态规划习题的详细讲解,帮助大家深入理解其本质,并掌握在实际问题中如何灵活运用。希望通过这篇文章,您能对动态规划的“自顶向下”与“自底向上”有更清晰的认识,从而在算法学习的旅程中迈出扎实的一步。下面我先从几个方面介绍动态规划。
用户11295429
2024/12/20
1470
解锁动态规划的奥秘:从零到精通的创新思维解析(1)
动态规划 —— 路径问题-下降路径最小和
https://leetcode.cn/problems/minimum-falling-path-sum/description/
迷迭所归处
2024/11/19
1020
动态规划 —— 路径问题-下降路径最小和
【算法专题】动态规划之路径问题
题目:一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。 问总共有多少条不同的路径?
YoungMLet
2024/03/01
2150
【算法专题】动态规划之路径问题
【动态规划2】路径问题
动态规划在解决路径问题时非常常见,特别是在图论和网络优化问题中。一般来说,动态规划用于解决那些具有重叠子问题和最优子结构性质的问题。路径问题通常涉及找到从起点到终点的最佳路径,可以是最短路径、最长路径或者满足特定条件的路径等。
南桥
2024/07/26
1480
【动态规划2】路径问题
算法训练之动态规划(二)
这个题目需要讨论的是由左上角到右下角的路径总数~我们可以按照动态规划的步骤来进行一步步分析~
用户11352420
2025/04/11
240
算法训练之动态规划(二)
【动态规划】状态 dp
状态表示:以 dp[i][j] 为结尾,走到 dp[i][j] 位置时一共有几种方式
2的n次方
2024/10/15
960
【动态规划】状态 dp
【算法/训练】:动态规划DP
动态规划(Dynamic Programming,DP)是一种在数学、管理科学、计算机科学、经济学和生物信息学等领域中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。动态规划常常适用于有重叠子问题和最优子结构性质的问题
IsLand1314
2024/10/15
4370
【算法/训练】:动态规划DP
动态规划 —— 路径问题-礼物的最大价值
https://www.nowcoder.com/practice/2237b401eb9347d282310fc1c3adb134?tpId=265&tqId=39288&ru=/exam/oj
迷迭所归处
2024/11/19
1040
动态规划 —— 路径问题-礼物的最大价值
动态规划 —— 路径问题-不同路径 ||
https://leetcode.cn/problems/unique-paths-ii/description/
迷迭所归处
2024/11/19
2240
动态规划 —— 路径问题-不同路径 ||
DP:解决路径问题
二维动态规划(DP)模型是一种通过引入两个维度的状态和转移方程来解决复杂问题的技术。它在许多优化和组合问题中广泛应用,尤其是那些需要考虑二维数组或矩阵的情况。
用户11305458
2024/10/09
2020
DP:解决路径问题
动态规划 —— dp 问题-买卖股票的最佳时机III
https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iii/description/
迷迭所归处
2024/11/19
1060
动态规划 —— dp 问题-买卖股票的最佳时机III
推荐阅读
相关推荐
解锁动态规划的奥秘:从零到精通的创新思维解析(5)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档