前言
'入门'是良好的动机,但单纯学习模块可能效率缓慢。如果有实际项目驱动,实践效果会更好。知识体系中的知识点依赖关系复杂,不存在绝对的'入门点'。最好的方式是做一个较大的东西,在过程中学会所需技能。完全可以在做爬虫的过程中学习 Python。
本文主要讲解爬虫的'道'和'术'——爬虫工作原理及 Python 实现。
核心学习内容
- 基本的爬虫工作原理
- 基本的 HTTP 抓取工具(如 Scrapy)
- Bloom Filter(布隆过滤器):用于大规模 URL 去重
- 分布式爬虫概念:维护集群机器有效分享的分布式队列(如 python-rq)
- RQ 和 Scrapy 的结合
- 后续处理:网页析取、存储(如 MongoDB)
爬虫工作原理
想象你是一只蜘蛛,被放到互联'网'上。你需要遍历所有网页。
- 初始页面:从某个地方开始(initial pages),例如人民日报首页。
- 链接提取:在首页看到各种链接,跳转到新页面(如国内新闻)。
- 去重机制:发现新页面有链回首页的链接。作为智能蜘蛛,需记录已访问过的地址。每次看到新链接,先检查是否已访问过。如果去过,则跳过。
理论上,如果所有页面可以从 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): # 提取当前页链接
if next_url not in seen:
seen.add(next_url)
url_queue.put(next_url)
else:
break
这是所有爬虫的核心逻辑。下面分析为什么爬虫实际上非常复杂。
效率优化
直接运行上述代码爬取整个豆瓣可能需要很长时间。问题在于待爬网页太多,且判重效率低。
- 复杂度问题:假设全网有 N 个网站,使用 set 判重复杂度为 O(logN)。内存使用效率也不高。
- Bloom Filter:通常做法是使用布隆过滤器。它使用固定内存(不随 URL 数量增长),以 O(1) 效率判定 URL 是否已存在。缺点是存在极小概率误判(即认为未访问过的 URL 已访问过),但在分配足够内存时,不确定性可忽略不计。这保证了不会漏掉未访问网页,仅可能少量重复访问。
- 并发处理:单台机器带宽有限,需使用多线程或多进程加速下载。


