Python爬虫实践——简单爬取我的博客

学任何一门技术,如果没有实践,技术就难以真正的吸收。利用上次博客讲解的三个知识点:URL 管理器、网页下载器和网页解析器来爬取一下我的博客。

我的博客地址

http://weaponzhi.online/

这个博客里面没有技术的文章,主要是我的一些生活上面的记录,可以说是我的日记本,平时会写一些思想感悟,记录些琐事。我们简单以这个博客主页为入口,爬取一下以 weaponzhi.online 为 host 下所有的 URL 。

首先当然是需要一个 URL 管理器了,但和上篇文章说的有所不同,这次我们的待爬取数据结构是队列,实际上 Python 本身的 list 已经可以实现队列的一些操作了,但 list 的一些队列操作比如 pop() 效率是比较低的,Python 官方推荐使用 collection.deque 来完成队列操作。

from collections import deque

queue = deque()  # 待爬取的队列
visited = set()  # 已爬取的set

host = 'http://weaponzhi.online'  # 入口页面, 可以换成别的
queue.append(host)

host 是我们的入口界面同时也作为一个 host 作为后续 URL 拼接使用,这个到后面再说。

count = 0  # 计数器

while queue:

    url = queue.popleft()  # 队首元素出队
    visited.add(url)  # 标记为已访问

    print('已经抓取: ' + str(count) + '   正在抓取 <---  ' + url)
    count += 1
    try:
        url_response = urllib.request.urlopen(url)
        # 过滤.jpg这种非跳转URL的情况
        if 'html' not in url_response.getheader('Content-Type'):
            continue
        data = url_response.read().decode('utf-8')
    except:
        continue

URL 管理器相关的数据结构建立好后,我们就可以从入口开始进行我们网页下载器部分的编写了。

我们先从待爬取的队列中 pop 出一个 URL,注意,pop 开头的方法在获取元素的同时会将元素从队列中移除。当我们获取完待爬取的元素的同时也将该 URL 添加到已爬取 URL 容器管理。

因为我们是一个简单的爬虫,并没有作任何的异常处理,所以为了避免爬取过程中遇到一些网络异常状况导致爬虫程序终止,我们将网页下载器的关键代码部分都 try...except 了,在遇到特殊情况的时候,将继续循环流程。

这里处理了一种情况,因为有的 URL 是一个下载链接或者图片,以 .jpg 或者 .ico 结尾,这种情况我们应该通过判断 header 属性机智的跳过它。

到现在为止都是上一篇文章的内容,不是很难,最复杂和需要花时间处理逻辑的,还是我们的网络解析器部分。

我先小试牛刀,在刚刚的 while 语句下写下了这段代码。

soup = BeautifulSoup(data, 'lxml')
node = soup.find_all('a')  # 查找a标签节点
for x in node:
    try:
        new_url = x['href']
        if new_url not in queue and new_url not in visited:
            queue.append(new_url)
            print('加入队列 ---> ' + new_url)
    except:
        continue

我使用 lxml 作为解析器,这种解析器的速度比 html.parser更快,而且它在 Python 各平台的兼容性也非常好。

我们通过 find_all 拿到了一个节点列表,需要注意的是,通过 soup 对象 find 函数返回的对象类型是bs4.element.Tag,Tag 与 XML 和 HTML 原生文档中的 tag 相同,它有两个重要属性 Name 和 Attributes,在这个例子中,name 就是标签名 a,Attributes 有很多,比如这里的 href,还有 class,id 等等。Attributes 的使用方法和字典一模一样,比如 x['href']。

上面的解析器代码输出的结果如下图所示

从结果来看这个爬虫还是有一定问题的,首先,爬取的 URL 大多都是相对路径,这种路径使用 urlopen 是肯定没法读取的。其次,我们看到我们会爬取到一些和博客地址无关的路径,比如图中的知乎地址,出现这种情况的原因是博客会有一些路径的跳转入口,如果我们放任爬虫去爬取这些路径,除非我们限定了爬取数量,那么爬虫将会无限制的爬取下去,直到天荒地老。

我们的目的是只爬取以 weaponzhi.online 开头的博客内地址,并且记录爬取数,如果队列中的 URL 全部出队,则自动停止循环,修改后的代码如下所示

for x in node:
    try:
       new_url = x['href']
       if new_url.startswith('/'):
            new_url = host + new_url
        if new_url not in queue and new_url not in visited:
            if 'http' in new_url and 'weaponzhi' in new_url:
                queue.append(new_url)
                print('加入队列 ---> ' + new_url)
    except:
        continue

我这里的处理方式比较简单粗暴,如果 URL 是以 '/' 开头的,我就认为它是一个相对地址,并把该地址与 host 地址作一个拼接。然后,用一个判断语句,确保该 URL 内有 weaponzhi 字段,从而保证了 URL 是博客内地址。当然了,更好的方式是使用正则表达式来代替这些判断语句,这就留给各位看官自行思考了~

来看看现在的代码结果

我将源码上传到了 Github 上,以后相关的文章都会在这个仓库中拓展。

https://github.com/WeaponZhi/PythonSpiner

原文发布于微信公众号 - WeaponZhi(WeaponZhi)

原文发表时间:2018-01-22

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏java工会

DOC文档注释,让你的代码如此清晰。

1684
来自专栏GreenLeaves

一、源代码-面向CLR的编译器-托管模块-(元数据&IL代码)

本文脉络图如下: ? 1、CLR(Common Language Runtime)公共语言运行时简介 ? (1)、公共语言运行时是一种可由多种编程语言一起使用的...

22310
来自专栏腾讯Bugly的专栏

Duang~ Android堆栈慘遭毁容?精神哥揭露毁容真相!

最近精神哥接到多个小伙伴的投诉,说无法看懂Bugly崩溃克星页面上显示的堆栈信息!精神哥赶紧把正研究的Top Crash崩溃和心爱的鸡爪放下,开始着手跟进。经分...

3075
来自专栏信安之路

PE 病毒与 msf 奇遇记

通俗的讲,PE 病毒就是感染 PE 文件的病毒,通过修改可执行文件的代码中程序入口地址,变为恶意代码的的入口,导致程序运行时执行恶意代码。

610
来自专栏小曾

通俗易懂,什么是.NET?什么是.NET Framework?什么是.NET Core?

什么是.NET?什么是.NET Framework?本文将从上往下,循序渐进的介绍一系列相关.NET的概念,先从类型系统开始讲起,我将通过跨语言操作这个例子来逐...

1282
来自专栏菩提树下的杨过

velocity模板引擎学习(1)

velocity与freemaker、jstl并称为java web开发三大标签技术,而且velocity在codeplex上还有.net的移植版本NVeloc...

1915
来自专栏小狼的世界

使用Python读取Mp3的标签信息

MP3是音频文件最流行的格式,它的全称是 MPEG layer III。但是这种格式不支持对于音频内容的描述信息,包括歌曲名称、演唱者、专辑等等。

1093
来自专栏数据结构与算法

HDU 5215 Cycle(dfs判环)

\(T\)组数据,给出\(n\)个点\(m\)条边的有向图,问是否存在一个奇环/偶环

522
来自专栏哲学驱动设计

巧用Using跳过异常捕获

前言     这里主要说一个使用using躲过异常的小技巧。     我原来就遇到过类似的问题好几次了,也没想到办法,直接有一天,调试得实在受不了了,才认真想了...

1869
来自专栏AI

在Atom中设置Python开发环境

当然,这里有很多很棒的文本编辑器。Sublime Text,Brackets,Atom。我一直都是Atom的粉丝,因为它是完全免费的,它有很多可用的包和主题,使...

3587

扫码关注云+社区