python爬图指南
我小时候曾在《科学美国人》上拜读过一篇文章,文中对比了地球上各种不同物种的移动速率,比如熊、猩猩、浣熊、鸟类、鱼类等——当然还有人类——计算它们每移动一公里消耗的热量,最后秃鹫赢了,它的移动效率最高。作为万物之灵的人类,排在倒数第几位。但是杂志特地测量了人类骑自行车的速率。结果把秃鹫远远甩在了身后,在排名上遥遥领先。这篇文章给我留下了深刻的印象,人类擅长发明工具,工具赋予我们奇妙的能力。 苹果以前有一条广告:计算机是头脑的自行车 ,我彻头彻尾地坚信如果将来有人回顾人类历史,计算机将是人类最伟大的发明。
----Steve Jobs(对,就是乔布斯说的,你没看错!!)
那么,正事来了,如何高效看图(别问我看什么图)。
下面的内容就是,当我们有了一定的python基础,如何写这样的一个宅男爬虫(也就是实现打开网页,寻找网页中所有存有网页链接的图片,然后download图片,并且保存在我们指定的文件夹中)。
在我的爬虫中用到了re,os,threading,requests,time
这几个模块,其中我使用request
模块,替代了官方的urllib2
,为毛用requests 不用urllib2,那是因为request
的官方文档中的这句话迷住了我:"Requests is the only Non-GMO HTTP library for Python, safe for human consumption.",嘎嘎。
下面正式说思路:我们平时浏览网页,都是在浏览器中输入网址,然后等待网站返回数据,浏览器将网页加载显示出来。在这个过程中,主要是如下几步:
- 浏览器向目标网站服务器发送请求,
- 目标服务器接受请求,
- 目标服务器发送响应数据到浏览器。
- 浏览器再将获取的数据解析,形成你所看到的网站(要想更详细的了解整个过程参见书: 计算机网络(自顶向下法))
目标服务器的响应数据应该长这个样子(有点丑,是吧,哈哈):
<head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a>
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;and they lived at the bottom of a well.
</p>
<p class="story">...</p>
这些标题通常有特殊含义:例如<title></title>
表示文章标题,<a></a>
表示链接,<img href = "......" />
表示图片链接,我们就要获取<img>
中href
参数的数据,这里储存着我们需要获取的图片链接地址。然后再打开这个链接,获取里面的图片数据保存就大功告成了。
steps (只描述实现思路,代码起描述作用!!!)
静觅爬虫系列教程(不错的爬虫教程)
下面按步骤介绍实现思路,当你实现时,应该各个功能封装成函数,或者封装成类,并且加入异常监测,以保证代码运行的稳定性,并且将程序中出现的错误记入写入log,方便以后查看。
- 调用类似下面的代码,获取我们所需的网站内容(也就是HTML文本,CSS样式表,JavaScript):
import requests
web = requests.get('http://www.baidu.com')
print web.text```
2. 编写正则表达式,以某种特定格式匹配我们需要获取的内容,然后将获取内容保存:
import request
import re
page = 1
url = 'http://www.qiushibaike.com/hot/page/' + str(page)
user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
有些服务器会对请求进行验证,加入headers装作我是好人
headers = { 'User-Agent' : user_agent }
获取目标站的Http代码
web = requests.get(url,headers=headers)
根据目标站的Http代码,找到我们要获取的内容格式特点,书写正则,并测试
pattern = re.compile('<div.?author">.?<a.?<img.?>(.?)</a>.?<div.?'+
'content">(.?).?</div>(.?)<div class="stats.?class="number">(.?)</i>',re.S)
所有的查找匹配结果都会储存在imgurl这个列表中
imgurl = re.findall(pattern,web.content)
3. 既然我们成功获取了要匹配的数据(我假设是图片链接),那么就可以打开图片链接进行处理
import request
import re
import os
page = 1
url = 'http://www.qiushibaike.com/hot/page/' + str(page)
user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
有些服务器会对请求进行验证,加入headers装作我是好人
headers = { 'User-Agent' : user_agent }
获取目标站的Http代码
web = requests.get(url,headers=headers)
根据目标站的Http代码,找到我们要获取的内容格式特点,书写正则,并测试
pattern = re.compile('<div.?author">.?<a.?<img.?>(.?)</a>.?<div.?'+
'content">(.?).?</div>(.?)<div class="stats.?class="number">(.?)</i>',re.S)
所有的查找匹配结果都会储存在imgurl这个列表中
imgurl = re.findall(pattern,web.content)
创建要保存的文件夹
os.mkdir('/home/picture')
for item in imgurl:
imgdata = requests.get(item,headers=headers)
picorder = picorder + 1
f = open('/home/picture/'+str(picorder),'rw')
f.write()
f.flush()
f.close()
4. 当上面所有的都完成之后,你良好的运行一阵,是否觉得下载图片太慢,那么下面我们再加入多线程
>**CPython**实现细节:在Cpython,由于全局解释器锁(Global interpreter Lock GIL),每次只能有一个线程可以 执行Python 代码(即使某些以效率为导向的库(performance-oriented libraries)可能克服这些限制)。如果你希望你的应用更好的利用电脑的多核资源。建议你使用**multiprocessing
** 或者**concurrent.futurres.ProcessPollExector
**模块。然而多线程仍然是适当的模块,当你使用多IO并行任务时(multiple I/O - bound tasks simultaneously)
import request
import re
import os
page = 1
url = 'http://www.qiushibaike.com/hot/page/' + str(page)
user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
有些服务器会对请求进行验证,加入headers装作我是好人
headers = { 'User-Agent' : user_agent }
获取目标站的Http代码
web = requests.get(url,headers=headers)
根据目标站的Http代码,找到我们要获取的内容格式特点,书写正则,并测试
pattern = re.compile('<div.?author">.?<a.?<img.?>(.?)</a>.?<div.?'+
'content">(.?).?</div>(.?)<div class="stats.?class="number">(.?)</i>',re.S)
所有的查找匹配结果都会储存在imgurl这个列表中
imgurl = re.findall(pattern,web.content)
创建要保存的文件夹
os.mkdir('/home/picture')
picorder = picorder +1
当要下载内容不空时,开启4个下载线程
while items:
if threading.activeCount()<5:
a = threading.Thread(target=downfunc,args=(items.pop(),picoder))
a.start()
定义一个下载函数
def downfunc(url,order)
imgdata = requests.get(url,headers=headers)
f = open('/home/picture/'+str(order),'rw')
f.write()
f.flush()
f.close()
整体代码思路就向上面类似,不过自己实现要学习**```request,re,threading,os```**这几个库,关于匹配还可以引入**```beautifulsoup```** 或者**```xpath```**更方便快捷的解析```HTML```文本。革命尚未成功,同志仍需努力!!!!!!