从零开始写一只爬虫 · 排排坐吃果果

从零开始写一只爬虫
这里需要用到 队列 和 宽度优先搜索(BFS)

什么是队列?

(详细说明请翻阅 维基百科

你去食堂打饭,人多,要排队是吧?队伍头部的人正在被服务(打饭),新来的人只能跑到队伍最后面,眼巴巴地看着。队头的人打完饭了,就离开队伍,座到旁边吃去了。此时第二名变成了对头,开始打饭……

也就是说,新来的只能加在队伍最后面,而队头才是我们永远的候选。选中它,操作它,扔掉它。

Python 的列表很魔性啊!数组、队列、栈三合一!很神奇!怪不得列表是 Python 的“苦力”。

那么宽度优先搜索呢?

(详细说明请翻阅 维基百科

队头的人打完饭,拿出手机,给室友们打电话:“喂,想吃饭的话自己来打饭,老子不给你们带饭了”。室友们接到电话,立刻闪现过来,然而无奈发现只能去队伍后面默默排队,顺带看着刚才 Call 自己的那位猪队友优雅地离开队伍,坐旁边吃去了。

第二个人也是如此。队伍好像变长了。

第三个人木有室友……

第四个人打了电话,然而室友叫了外卖,不来打饭了……

总之呢,队伍总会排完的。

ok,爬虫也是这样,拿到一个页面之后,在抓取下自己感兴趣的东西之后,顺带着将这个页面中的所有超链接都找了出来,记录下来,加入到一个队列里面。然后,只要队列不空,就取出队头,访问这个 URL,继续抓取、找出链接、放入队列……

在这里我们先考虑一种简单的情况:事先就能把全部的网址都构造出来,放入队列中,不考虑队列会在抓取过程中被动态地添加进去新的 URL。这样便于测试,并且在大多数时候是很有效的。

为什么?仔细看 URL,对于一部分网站来说,URL 都是有规律的:

把后面的 129 换成其他数字试试?发现了什么?

另外还有一个好处:队伍长度一直在减少。这样就不会出现“一个网页被访问多次”的尴尬局面了。至于“将网址动态添加到队列中”的情形,我们以后再讨论。

排排坐

这个不难,一个 for 循环就全都出来了:

吃果果

当队列不为空的时候,取出队头,进行抓取:

当然,我们构造出来的 URL 有可能会导致 404。因为我们是尝试打开了几个网页后就假设它的 id 号是连续增加的。如果 404 了怎么办?

跳过啊!这还用教!

也就是说,如果网页返回 404, 或者从返回的网页中得不到我们想要的信息,跳过就好啦~天涯何处无芳草,少你一个不算少!吼吼!

写到这里,对于一个洁癖来说,我已经快受不了了。随着代码越来越多,不把各个功能都分成函数的话,我会疯掉的。

OK,下面是代码重写后的结果。

看起来舒 (zhuang) 服 (bi) 多了吧?

发表评论

电子邮件地址不会被公开。 必填项已用*标注