来,让我们写一个网络爬虫,下载页面上所有的照片吧!

什么是网络爬虫?

网络爬虫是一种非常有意思的程序。偌大的Internet,就像是一只蜘蛛织成的大网:一个个超级链接就是蛛丝,将无数页面连接起来,而网络爬虫,则会沿着一根根蛛丝,爬遍每一个节点……

网络爬虫

网络爬虫能干嘛?

蜘蛛在网上爬来爬去,当然不是为了健身。它会在网上寻觅猎物,捕捉它们,并拖回自己的窝里。

举一个例子:某天某日的清晨,老板突然让你将雪球网上所有的A股行情信息全部保存到一个Excel文件里,以便他浏览。你点开了网址雪球(A股行情),惊喜地发现有三十四页,一条一条复制,显然又累又笨,但是老板要看,你又不得不从,惆怅啊……

很多时候,我们会需要做这样的工作:将某一类型的文档全部下载保存下来,然后进行分析。一个一个点击鼠标,显然不现实。那么,就做一个网络爬虫吧,自动化地把需要的东西保存下来。

网络爬虫是怎么干的?

一个简单的网络爬虫的逻辑并不复杂,就是模仿人类浏览网页的动作:输入网址,进入页面,浏览网页,点击链接,进入下一页面……周而复始。

当然,嘴上说是这样,还得要将步骤细化一下。所以先来看看浏览网页的时候,我们做了些什么。

当我们浏览网页的时候,浏览器在做些什么?

蒂姆·伯纳斯-李在发明互联网的时候,为了解决页面之间相互连接的问题,让网络浏览更加方便,发明了超文本标记语言HTML。它是一个文本文档,但是文档中会有一些特殊的标记——标签,它可以标记出哪些位置的信息是标题,哪些位置的信息是文本,哪些地方是图像,哪些地方是超级链接。它就长这样。

HTML

尖括号中间的就是标签,里面的字就是标签的名字,带斜杠的表示标记结束了。比如,<p>的意思是段落,</p>的意思就是这一段结束了。

浏览器可以根据标签,将网页依照代码的意思表现出来,用点儿术语的话,就是浏览器是一个HTML的解释器。当我们浏览网页的时候,浏览器会先将网页的HTML文件,以及所需要的其它元素都下载到你的电脑里,然后根据HTML文件的内容,将网页展现在你的面前。

所以网络爬虫也需要干这件事情:下载HTML文件,然后分析它,根据分析的结果将需要的文本或者图像什么的下载下来,找到超级链接,继续……

让我们写一个网络爬虫,下载页面上所有的照片吧!

知乎上有很多提问,下面会有很多照片,比如这个怎么用手机拍出精彩的照片?,图片都挺好看的,我想全部下载下来,怎么办呢?打开页面以后,右键点击页面,选择【查看源文件】,就可以看到HTML文件的内容了。简单分析一下,会发现照片其实都在这样的标签下面:

img标签

所以,现在就可以制定出我们的策略了:打开页面,分析它的HTML源文件,找出所有img标签,将里面的图片都保存下来,over!

用Python实现你的第一个网络爬虫

Python语言语法简单而灵活,实用的库(别人写好,可以直接实用的代码)非常多,很适合写这种小爬虫。所以我们用Python来写一个网络爬虫。可以点击这里下载Python环境的安装包,一直下一步就可以安装好了。具体学习Python可以看这本书,或者这本书。这里我们的代码并不复杂,需要的知识点不多,我会一点一点讲解的。当然你可能需要一点点程序设计的知识。

在一个文本编辑器里面输入以下代码:

#-*-coding:utf-8-*-

import urllib

url = "https://www.zhihu.com/question/20922273"

page = urllib.urlopen(url)

print page.read()

找一个文件夹,保存为example1.py。然后点击右键选择【EDIT with IDLE】。

打开以后按F5键。应该会出现这样的窗口。

是不是打印出了原来页面的HTML文件的内容?

下面来解释一下这一段代码的意思。

#-*-coding:utf-8-*- 的意思是这一段Python程序的编码格式是UTF-8。理解这一点需要一些编码的知识,这里暂时不用管它。一般每一个Python程序第一句话都是这个。

import urllib 的意思是导入urllib库,python自带的一个网络库,我们可以用它来实现访问网页,下载文件等功能。当然还有很多功能更高级的库,比如urllib2或者requests等,这里我们挑一个简单的先。

url = "https://www.zhihu.com/question/20922273" 这句话的意思是定义url为字符串"https://www.zhihu.com/question/20922273" ,也就是我们要访问的网页的网址,可以看出,网址实际上是一个字符串变量。

page = urllib.urlopen(url) 这句话的意思是使用urllib库里面的urlopen函数,打开网址url,并把打开的这个对象命名为page(打开了一个东西,虽然我们不知道它是什么,但是先给它起个名字吧!)。

page.read() 的意思就是读取page这个对象的内容。print page.read()的意思自然就是打印这个内容了。

于是,我们就完成了第一步,打开页面。下面,我们来写程序分析打开的页面。

写程序,找出所有的图片地址

在IDLE里面,把前面写的代码改一改。

#-*-coding:utf-8-*-

import urllib

from sgmllib import SGMLParser

class ZhihuParser(SGMLParser):

imgList = []

def reset(self):

    SGMLParser.reset(self)  #初始化

    self.imgList = []

    def start_img(self, attrs):

    imgUrl = [v for k, v in attrs if k=='data-original']

    if imgUrl:

        self.imgList.append(imgUrl[0])

        imgUrl = ""

        url = "https://www.zhihu.com/question/20922273"

        page = urllib.urlopen(url)

        parser = ZhihuParser()

        parser.feed(page.read())

        print parser.imgList

点击F5运行,看看结果。


下面来解释一下代码。

from sgmllib import SGMLParser 这一句的意思是从sgmllib文件里面导入SGMLParser这个包。这个包是Python自带的一个解析HTML的库。

class ZhihuParser(SGMLParser):是定义一个类ZhihuParser,它继承SGMLParser这个类。我们对它进行一些修改。

imgList = [] 声明了一个列表,我们用它来保存所有图片的地址。

def reset(self): 这个函数是ZhihuParser类的初始化函数。每一次生成ZhihuParser类的对象的时候都会调用这个函数。我们让这个函数先初始化SGMLParser.reset(self),然后把列表制空self.imgList = []。

def start_img(self, attrs): 这个函数是解析img标签的函数。当SGMLParser遇到一个img标签的时候,就会调用这个函数。比如我们要解析<a>标签,那就自己定义一个函数start_a,解析标签,就定义一个函数start_head,函数的内容是我们需要的动作。对于这样的结束标签,对应的函数是end_something(self)。

start_something函数的参数是(self,attrs)。self自然就是类本身,attrs是SGMLParser解析出来的标签参数,比如知乎img的代码:

里面的src, data-rawwidth等等,都是标签的参数,它以字典的形式传入函数中,即一系列参数名:参数的二元对。这里我们需要提取出地址,即data-original的内容,imgUrl = [v for k, v in attrs if k=='data-original'],意思是遍历attrs,如果字典的名为data-original,就保存下来。

如果imgUrl保存成功,我们就把它导入到列表里,self.imgList.append(imgUrl[0])。然后将临时变量imgUrl制空(这句话其实不必要)。

parser = ZhihuParser()定义了一个ZhihuParser对象,parser.feed(page.read())将页面的内容传入parser,进行解析。print parser.imgList将所有的图片地址打印出来。

下面我们继续修改代码,把所有图片保存下来。

在上面的基础上加入如下代码:

cnt=1

for url in parser.imgList:

    f=open("%d.jpg"%cnt,'wb')

    img=urllib.urlopen(url)

    f.write(img.read())

    f.close()

    print "%d was done!"%cnt

    cnt += 1

cnt = 1是定义一个计数器,记录我们下载图片的个数。

for url in parser.imgList:遍历图片地址列表。

f = open("%d.jpg"%cnt,'wb')打开一个文件。我们将下载下来的图片写入这个文件中。

img = urllib.urlopen(url)打开图片地址。

f.write(img.read())将图片写入文件,然后关闭文件。

运行程序,不一会就看见我们将所有的网页上的图片都下载了下来。


于是乎,我们就完成了一个最简单的网络爬虫。

后    记

事实上,真正的通用网络爬虫是很难写的,要考虑的因素很多。比如怎样规避网站的反爬虫机制(有的网站可不愿意你下载文件,占用带宽),怎样避免爬虫陷阱(比如有两个页面有相互连接的超级链接,于是爬虫就会一直在这两个页面间爬来爬去,不去其他页面),怎样大规模快速地爬(分布式爬虫),怎样解析JavaScript等等等等。事实上,网络爬虫是搜索引擎的核心技术之一,google,百度等搜索引擎公司每天都不停地在网络上爬取页面,解析,并排序,给我们提供搜索服务。


PS:我不太懂怎么样在简书打代码。。。排版有点丑,请见谅。欢迎来我的Csdn看看,刚开始写,文章不多。我以后会在上面写一些我的学习笔记。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容