Python爬取图片(使用urllib2)

上篇文章 使用 XPath 提取网页信息 之后,将链接中的内容下载至本地,需要使用到 urllib2 。


urllib2 简介

urllib2提供一个基础函数urlopen,通过向指定的URL发出请求来获取数据。最简单的形式就是:

1
2
3
import urllib2 
response = urllib2.urlopen('/')
html = response.read()

可以将上述代码看作两个步骤,我们指定一个域名并发送请求

1
request=urllib2.request('/')

接着服务端响应来自客户端的请求

1
response=urllib2.urlopen(request)

运行结果

我们可以发现title这个地方本来应该是中文的,但因为编码的原因,导致出现乱码。通过将html页面重新用”utf-8”编码,可以解决这个问题。


将获得的response保存至本地

使用Xpath表达式提取图片链接

详见上一文章 /2016/12/13/get_html/ ,关于XPath和beautifulsoup,可以参考python中的beautifulsoup和xpath有什么异同点?

这里需要导入lxml,代码格式如下。

1
2
3
4
5
6
import requests
from lxml import etree
html = requests.get("http://jandan.net/ooxx")
html.encoding = 'utf-8'
selector = etree.HTML(html.text)
content = selector.xpath('//ol[@class = "commentlist"]//@src')

单独运行 以上代码可以获得
Xpath运行结果

设置保存的位置

需要使用到os库中的 os.chdir(r””)函数,””中间插入地址。注意这个位置必须是存在的,如果位置不存在,函数会报错。因为该函数的意义是:将工作空间从python代码所在位置,改为指定的这个位置。

模拟正常浏览器下载图片(如果Python下载的图片不显示 )

有时你会碰到,程序也对,但是服务器拒绝你的访问。这是为什么呢?

问题出在请求中的头信息(header)。 有的服务端有洁癖,不喜欢程序来触摸它。

这个时候你需要将你的程序伪装成浏览器来发出请求。请求的方式就包含在header中。

1
2
3
4
5
6
header = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36',
'Cookie': 'AspxAutoDetectCookieSupport=1',
}
request = urllib2.Request(imgurl, None, header)
response = urllib2.urlopen(request)

可以看到urllib2.Request()里边加入了一个header,用于模拟浏览器访问,第二个位置None表示data,用Python官方文档的说法:Sometimes you want to send data to a URL (often the URL will refer to a CGI (Common Gateway Interface) script [1] or other web application). With HTTP, this is often done using what’s known as a POST request.
暂时我们用不着,所以不深究,等我碰到这个问题了再说。

为图片命名(下载图片只有一张)

在获得response之后,将图片直接保存为某个特定名字的话。会导致之后抓取到的图片顶替掉之前的图片,导致图片看起来只有一张。

1
2
3
4
with open("%s.jpg" %name, "wb") as f:
f.write(response.read())
print(imgurl)
name += 1

使用with as语句,将文件名保存为%s.jpg,类似于C语言的输出。循环结束的时候name++,保证文件名不重复。

使用with as 函数

Python’s with statement provides a very convenient way of dealing with the situation where you have to do a setup and teardown to make something happen. A very good example for this is the situation where you want to gain a handler to a file, read data from the file and the close the file handler.
有一些任务,可能事先需要设置,事后做清理工作。对于这种场景,Python的with语句提供了一种非常方便的处理方式。一个很好的例子是文件处理,你需要获取一个文件句柄,从文件中读取数据,然后关闭文件句柄。

Without the with statement, one would write something along the lines of: 如果不用with语句,代码如下:

1
2
3
file = open("/tmp/foo.txt")
data = file.read()
file.close()

使用with as之后代码为:
1
2
with open("%s.jpg" %name, "wb") as f:
f.write(response.read())

总结

本文通过XPath表达式提取页面图片链接,使用urllib2下载,其中使用header模仿浏览器访问。解决了以下问题:

  • Python下载的图片不显示
  • 下载图片只有一张
  • 设置保存的位置
  • 使用with f函数

效果如下:
抓取到的图片

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# coding=utf-8
import requests
import urllib2
import os

from lxml import etree
html = requests.get("http://cl.d5j.biz/htm_mob/7/1612/2172569.html")
html.encoding = 'utf-8'
selector = etree.HTML(html.text)
content = selector.xpath('//table//img/@src')
for imgurl in content:
name = imgurl[-9:];
os.chdir(r"D:")
header = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36',
'Cookie': 'AspxAutoDetectCookieSupport=1',
}
request = urllib2.Request(imgurl, None, header) #刻意增加头部header,否则本行与下一行可以写为:response = urllib2.urlopen(imgurl)
response = urllib2.urlopen(request)
f = open(name , 'wb')
f.write(response.read())
f.close()
print(imgurl)

代码重新修改了一下,上手运行会发现D盘有惊喜哦~
加入print(imgurl),运行起来更洋气~
输入下载来源

Python爬取图片(使用urllib2)

https://iii.run/archives/842d34930c01.html

作者

mmmwhy

发布于

2016-12-15

更新于

2022-10-08

许可协议

评论