跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Python算法

Python 爬虫入门实战:项目驱动与核心原理

综述由AI生成Python 爬虫入门应通过项目驱动而非单纯学习模块。文章讲解了爬虫基本工作原理(如广度优先遍历、URL 去重),介绍了使用 Bloom Filter 优化判重效率的方法,以及基于 Master-Slave 架构的分布式爬虫实现思路。涵盖了 Scrapy、Redis、RQ 等工具的应用场景及后续数据处理要点。

宁静发布于 2025/2/7更新于 2026/6/928 浏览
Python 爬虫入门实战:项目驱动与核心原理

'入门'是良好的动机,但是可能作用缓慢。如果你手里或者脑子里有一个项目,那么实践起来你会被目标驱动,而不会像学习模块一样慢慢学习。

另外如果说知识体系里的每一个知识点是图里的点,依赖关系是边的话,那么这个图一定不是一个有向无环图。因为学习 A 的经验可以帮助你学习 B。因此,你不需要学习怎么样'入门',因为这样的'入门'点根本不存在!你需要学习的是怎么样做一个比较大的东西,在这个过程中,你会很快地学会需要学会的东西的。当然,你可以争论说需要先懂 python,不然怎么学会 python 做爬虫呢?但是事实上,你完全可以在做这个爬虫的过程中学习 Python。

先长话短说 summarize 一下:

你需要学习

  1. 基本的爬虫工作原理
  2. 基本的 http 抓取工具,如 Scrapy
  3. Bloom Filter: Bloom Filters by Example
  4. 如果需要大规模网页抓取,你需要学习分布式爬虫的概念。其实没那么玄乎,你只要学会怎样维护一个所有集群机器能够有效分享的分布式队列就好。最简单的实现是 python-rq:
  5. rq 和 Scrapy 的结合:darkrho/scrapy-redis
  6. 后续处理,网页析取,存储 (Mongodb)

以下是短话长说:

说说当初写的一个集群爬下整个豆瓣的经验吧。

1)首先你要明白爬虫怎样工作。
想象你是一只蜘蛛,现在你被放到了互联'网'上。那么,你需要把所有的网页都看一遍。怎么办呢?没问题呀,你就随便从某个地方开始,比如说人民日报的首页,这个叫 initial pages,用$表示吧。

在人民日报的首页,你看到那个页面引向的各种链接。于是你很开心地从爬到了'国内新闻'那个页面。太好了,这样你就已经爬完了俩页面(首页和国内新闻)!暂且不用管爬下来的页面怎么处理的,你就想象你把这个页面完完整整抄成了个 html 放到了你身上。

突然你发现,在国内新闻这个页面上,有一个链接链回'首页'。作为一只聪明的蜘蛛,肯定知道你不用爬回去的吧,因为你已经看过了啊。所以,你需要用你的脑子,存下你已经看过的页面地址。这样,每次看到一个可能需要爬的新链接,你就先查查你脑子里是不是已经去过这个页面地址。如果去过,那就别去了。

好的,理论上如果所有的页面可以从 initial page 达到的话,那么可以证明你一定可以爬完所有的网页。

那么在 python 里怎么实现呢?

很简单

import queue

initial_page = "http://www.renminribao.com"

url_queue = queue.Queue()
seen = set()

seen.add(initial_page)
url_queue.put(initial_page)

while True: #一直进行直到海枯石烂
    if not url_queue.empty():
        current_url = url_queue.get()    #拿出队例中第一个的 url
        store(current_url)               #把这个 url 代表的网页存储好
        for next_url in extract_urls(current_url): #提取把这个 url 里链向的 url
            if next_url not in seen:      
                seen.add(next_url)
                url_queue.put(next_url)
    else:
        break

写得已经很伪代码了。

所有的爬虫的 backbone 都在这里,下面分析一下为什么爬虫事实上是个非常复杂的东西——搜索引擎公司通常有一整个团队来维护和开发。

2)效率
如果你直接加工一下上面的代码直接运行的话,你需要一整年才能爬下整个豆瓣的内容。更别说 Google 这样的搜索引擎需要爬下全网的内容了。

问题出在哪呢?需要爬的网页实在太多太多了,而上面的代码太慢太慢了。设想全网有 N 个网站,那么分析一下判重的复杂度就是 N*log(N),因为所有网页要遍历一次,而每次判重用 set 的话需要 log(N) 的复杂度。OK,我知道 python 的 set 实现是 hash——不过这样还是太慢了,至少内存使用效率不高。

通常的判重做法是怎样呢?Bloom Filter. 简单讲它仍然是一种 hash 的方法,但是它的特点是,它可以使用固定的内存(不随 url 的数量而增长)以 O(1) 的效率判定 url 是否已经在 set 中。可惜天下没有白吃的午餐,它的唯一问题在于,如果这个 url 不在 set 中,BF 可以 100% 确定这个 url 没有看过。但是如果这个 url 在 set 中,它会告诉你:这个 url 应该已经出现过,不过我有 2% 的不确定性。注意这里的不确定性在你分配的内存足够大的时候,可以变得很小很少。

注意到这个特点,url 如果被看过,那么可能以小概率重复看一看(没关系,多看看不会累死)。但是如果没被看过,一定会被看一下(这个很重要,不然我们就要漏掉一些网页了!)。

好,现在已经接近处理判重最快的方法。另外一个瓶颈——你只有一台机器。不管你的带宽有多大,只要你的机器下载网页的速度是瓶颈的话,那么你只有加快这个速度。用一台机子不够的话——用很多台吧!当然,我们假设每台机子都已经进了最大的效率——使用多线程(python 的话,多进程吧)。

3)集群化抓取
爬取豆瓣的时候,我总共用了 100 多台机器昼夜不停地运行了一个月。想象如果只用一台机子你就得运行 100 个月了...

那么,假设你现在有 100 台机器可以用,怎么用 python 实现一个分布式的爬取算法呢?

我们把这 100 台中的 99 台运算能力较小的机器叫作 slave,另外一台较大的机器叫作 master,那么回顾上面代码中的 url_queue,如果我们能把这个 queue 放到这台 master 机器上,所有的 slave 都可以通过网络跟 master 联通,每当一个 slave 完成下载一个网页,就向 master 请求一个新的网页来抓取。而每次 slave 新抓到一个网页,就把这个网页上所有的链接送到 master 的 queue 里去。同样,bloom filter 也放到 master 上,但是现在 master 只发送确定没有被访问过的 url 给 slave。Bloom Filter 放到 master 的内存里,而被访问过的 url 放到运行在 master 上的 Redis 里,这样保证所有操作都是 O(1)。(至少平摊是 O(1)

考虑如何用 python 实现:
在各台 slave 上装好 scrapy,那么各台机子就变成了一台有抓取能力的 slave,在 master 上装好 Redis 和 rq 用作分布式队列。

代码于是写成

#slave.py

current_url = request_from_master()
to_send = []
for next_url in extract_urls(current_url):
    to_send.append(next_url)

store(current_url);
send_to_master(to_send)

#master.py
distributed_queue = DistributedQueue()
bf = BloomFilter()

initial_pages = "www.renmingribao.com"

while(True):
    if request == 'GET':
        if distributed_queue.size()>0:
            send(distributed_queue.get())
        else:
            break
    elif request == 'POST':
        bf.put(request.url)

好的,其实你能想到,有人已经给你写好了你需要的:

4)展望及后处理
虽然上面用很多'简单',但是真正要实现一个商业规模可用的爬虫并不是一件容易的事。上面的代码用来爬一个整体的网站几乎没有太大的问题。

但是如果附加上你需要这些后续处理,比如

  1. 有效地存储(数据库应该怎样安排)
  2. 有效地判重(这里指网页判重,咱可不想把人民日报和抄袭它的大民日报都爬一遍)
  3. 有效地信息抽取(比如怎么样抽取出网页上所有的地址抽取出来,'朝阳区奋进路中华道'),搜索引擎通常不需要存储所有的信息,比如图片我存来干嘛...
  4. 及时更新(预测这个网页多久会更新一次)

如你所想,这里每一个点都可以供很多研究者十数年的研究。虽然如此,

'路漫漫其修远兮,吾将上下而求索'。

所以,不要问怎么入门,直接上路就好了。

  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • C++ 就业导向的系统学习路径指南
  • Rust WebAssembly 与 Three.js 结合的 3D 数据可视化实战:高性能粒子系统
  • 本地 AI 绘画:麦橘超然 Flux 控制台部署与使用
  • 大语言模型(LLM)原理与应用实战
  • 大语言模型(LLM)原理与 LoRA 微调实战
  • Redis String 类型深度解析与 C++ 实战
  • RAG 与 Gemini 技术对比:大模型检索成本分析
  • 默认安全治理实践:水平越权检测与前端安全防控
  • 终极指南:5步掌握llama.cpp量化技术,让大模型内存占用直降70%
  • LG WebOS 电视第三方应用安装与 Root 权限指南
  • Spring Boot 集成 RabbitMQ 实战指南:从 Hello World 到高级配置
  • 基于 Neo4j 知识图谱的智能问答系统设计与实现
  • Qwen3-VL-WEBUI 视频时间戳对齐配置指南
  • Qwen3-Embedding-4B 基于 llama.cpp 的集成部署教程
  • MySQL 核心原理与实战进阶指南
  • Python 开发环境安装与配置指南
  • HashMap、ArrayMap 与 SparseArray 对比及选型指南
  • Android 开发成长有益的技能推荐
  • 前端文件下载实战:从原理到最佳实践
  • MySQL 数据库核心操作:创建、修改与备份实战

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online