Python从网上下载图片的方法

Download Images with Python

*本文所使用的Python版本为2.7

Part 1. urllib2

urllib2是Python标准库提供的与网络相关的库,是写爬虫最常用的一个库之一。
想要使用Python打开一个网址,最简单的操作即是:

your_url = "http://publicdomainarchive.com/"
html = urllib2.urlopen(your_url).read()

这样所获得的就是对应网址(url)的html内容了。

但有的时候这么做还不够,因为目前很多的网站都有反爬虫机制,对于这么初级的代码,是很容易分辨出来的。例如本文所要下载图片的网站http://publicdomainarchive.com/,上述代码会返回HTTPError: HTTP Error 403: Forbidden错误。

那么,在这种情况下,下载网络图片的爬虫(虽然只有几行代码,但一个也可以叫做爬虫了吧,笑),就需要进一步的伪装。

要让爬虫伪装成浏览器访问指定的网站的话,就需要加入消息头信息。所谓的消息头信息就是在浏览器向网络服务器发送请求时一并发送的请求头(Request Headers)信息和服务器返回的响应头(Response Headers)信息。

例如,使用FireFox打开http://publicdomainarchive.com/时所发送的Request Headers的部分内容如下:

Host:"publicdomainarchive.com/"
User-Agent:"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0"
Accept:"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
...

还有一些其他属性,但其中伪装成浏览器最重要的部分已经列出来了,即User-Agent信息。

要使用Headers信息,就不能再仅仅向urlopen方法中传入一个地址了,而是需要将HTTP Request的Headers封装后传入:

headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0'}
req = urllib2.Request(url = url, headers = headers)
content = urllib2.urlopen(req).read()

这样,就获得了网站的html内容。

接下来,就需要从html去获取图片的链接。

Part 2. HTMLParser

HTMLParser是Python提供的HTML解析库之一。

但Python提供的这个类中很多方法都没有实现,因而基本上这个库只负责进行解析,但解析完了什么都不做。所以如果需要对HTML中的某些元素进行加工的话,就需要用户自己去实现其中的一些方法。本文仅实现其中的handle_starttag方法:

class MyHTMLParser(HTMLParser): #继承HTMLParser类
    def __init__(self):         #初始化
        HTMLParser.__init__(self)

    def handle_starttag(self, tag, attrs):
        #参数tag即由HTMLParser解析出的开始标签,attrs为该标签的属性
        if tag == "img":       #下载图片所需要的img标签
            if len(attrs) == 0: pass
            else:
                for (variable, value)  in attrs:
                    #在attrs中找到src属性,并确定其是我们所要下载的图片,最后将图片下载下来(这个方法当然也有其他的写法)
                    if variable == "src" and value[0:4] == 'http' and value.find('x') >= 0:
                        pic_name = value.split('/')[-1]
                        print pic_name
                        down_image(value, pic_name)

Part 3. 下载图片

handle_starttag方法中,我们已经获得了图片的url,那么,最后一步,我们要下载图片了。

当然,要获得网络上的图片,自然也需要向服务器发送请求,一样需要用到urllib2这个库,也需要用到上面所用到的请求头。

以下是down_image()方法的主要代码:

binary_data = urllib2.urlopen(req).read()
temp_file = open(file_name, 'wb')
temp_file.write(binary_data)
temp_file.close()

因为这次打开的网址是个图片,所以urllib2.urlopen(req).read()所获取的就是图片的数据,将这些数据需要以二进制的方式写入本地的图片文件,即将图片下载下来了。

因为图片的url的最后一部分是图片的名字,所以可以直接用做本地的文件名,不用担心命名冲突,也不用担心后缀不符,很是方便。

Part 4. getFreeImages.py

这个下载图片的脚本的完整代码如下:

import urllib2,os
from HTMLParser import HTMLParser  

class MyHTMLParser(HTMLParser):
    def __init__(self):
        HTMLParser.__init__(self)
        #self.links = {}

    def handle_starttag(self, tag, attrs):
        #print "Encountered the beginning of a %s tag" % tag
        if tag == "img":
            if len(attrs) == 0: pass
            else:
                for (variable, value)  in attrs:
                    if variable == "src" and value[0:4] == 'http' and value.find('x') >= 0:
                        pic_name = value.split('/')[-1]
                        print pic_name
                        down_image(value, pic_name)


def down_image(url,file_name):
    global headers
    req = urllib2.Request(url = url, headers = headers)
    binary_data = urllib2.urlopen(req).read()
    temp_file = open(file_name, 'wb')
    temp_file.write(binary_data)
    temp_file.close()



if __name__ == "__main__":
    img_dir = "D:\\Downloads\\domain images"

    if not os.path.isdir(img_dir):
        os.mkdir(img_dir)

    os.chdir(img_dir)
    print os.getcwd()
    url = ""
    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0'}
    all_links = []
    hp = MyHTMLParser()

    for i in range(1,30):
        url = 'http://publicdomainarchive.com/public-domain-images/page/' + str(i) + '/'
        req = urllib2.Request(url = url, headers = headers)
        content = urllib2.urlopen(req).read()
        hp.feed(content)

    hp.close()

PS.脚本可以继续优化,以后再说吧。笑。

你可能感兴趣的:(简单的代码)