Python小项目——图片素材下载器

这是学python的时候做的一个大作业,当时花了几天时间,有点仓促,但是能完成这样,心里还是挺满意的。
一、程序简介
本次作业做的是一个图片素材下载器,通过键盘输入搜索关键字,自动下载百度图片或者千图网上的一些素材。
二、分析、开发、测试过程介绍
2.1软件开发环境
Python 3.5.2 Pycharm
2.2 代码文件
本程序包含一个主程序PhotoSpider.py以及一个数据文件word.data
2.3 成果展示
此软件采用tkinter相关库文件的GUI编程实现图形化界面。下图为下载器界面。

图1
通过界面可以看出,本下载器通过在搜索框输入关键字,图片来源和图片数量均为下拉框选项。图片可以选择来源于百度图片或者千图网,数量设置上预选项有10,20,50,当然也可以自己手动输入。测试时,程序默认是10。在搜索框输入关键字(例如‘老虎’),选择百度图片,点击‘download’,程序便会在百度图片上搜索老虎跳转的界面下载图片,在我的pycharm上会显示以下程序运行提示信息
这里写图片描述
图2
然后点击‘view’,会打开文件存储的路径,如图3所示,根据日期可进入相关文件夹查看自己下载的素材文件,如图4。
这里写图片描述
图3
这里写图片描述

                   图4

2.4 代码分析
具体代码分析可参照代码,代码注释很详细,这里简述大致内容。
程序流程如下:
界面布局->通过关键字合成目的网页url->获取html文件内容->进行正则表达式匹配->下载图片
界面布局方面除结合课件外参考了网上一个小程序代码(网址为:http://www.mincoder.com/python/745.shtml)界面的表格式布局,这一点和先前学习html时比较相像。通过先打草稿,精心计算,便能编写出整齐有序的界面了。通过输入关键字得到相关的url这部分也很关键。对于百度来说,通过比对发现在百度图片网页中输入内容后,会跳转到另外的界面,而这些界面的url都有一个共同点,就是以‘http://image.baidu.com/search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=result&fr=&sf=1&fmq=1483107461636_R&pv=&ic=0&nc=1&z=&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&ctd=1483107461636%5E00_1333X671&word=’为开头,然后加上输入内容的utf-8编码,也正是这个原因,才能实现抓取自己想抓取的图片。所以需要对输入的内容进行编码转换,这其中包括小写改大写,用‘%’代替‘\x’,以及去掉前两位和最后一位(该三位为b’’)。通过如下代码实现:
c=c.upper()
c=c.replace(“\X”,”%”)
d=c[2:len(c)-1]
对于千图网来说,他转向的页面的url格式为:’http://www.58pic.com/tupian/‘+输入内容的汉语拼音+’.html’
这其中汉字转向汉语拼音的函数参照于:https://github.com/cleverdeng/pinyin.py
Html文件内容的获取是通过库函数实现,由于网页上的图片大部分为JPG格式,故采用表达式’http://[\S]*.jpg’进行匹配,获得图片地址,图片文件夹父目录以日期命名,图片文件夹以输入内容命名,图片以下载序号命名,而后将图片内容写入电脑。
三、程序代码
PhotoSpider.py

import urllib.request
import urllib
import os
import time
from tkinter import ttk
from  tkinter import *

#获取网页源代码
def download(url):
    #伪装成浏览器访问
    headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) '
                             'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.80 '
                             'Safari/537.36'}
    # 读取数据
    request = urllib.request.Request(url, headers=headers)
    response=urllib.request.urlopen(request)
    data = response.read()
    return data

#进行匹配,下载图片文件
def getimg(word,num):
    #获取网页来源下表
    way = numberChosen['values'].index(numberChosen.get())
    #获取搜索框输入内容
    word2 = word.get()
    #获取图片数量
    count= int(num.get())
    #根据图片来源生成URL
    if way==0:
        c = str(word2.encode("utf-8"))#转换输入内容
        c = change(c)
        url = 'http://image.baidu.com/search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=result&fr=&sf=1&fmq=1483107461636_R&pv=&ic=0&nc=1&z=&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&ctd=1483107461636%5E00_1333X671&word=' + c
    elif way==1:
        #汉字转化为拼音
        test = PinYin()
        test.load_word()
        string = word2
        str1=''
        word2=test.pinyin1(string=string)
        for i in range(len(word2)):
            str1+=word2[i]
        print(str1)
        url='http://www.58pic.com/tupian/'+str1+'.html'
    else:
        pass
    #获取html内容
    html = download(url)
    #正则表达式匹配
    reg=r'http://[\S]*\.jpg'
    pattern=re.compile(reg)
    get_img=re.findall(pattern,repr(html))
    num=1
    #用时间给下载图片文件夹命名
    t = time.localtime(time.time())
    foldername = str(t.__getattribute__("tm_year")) + "-" + str(t.__getattribute__("tm_mon")) + "-" + str(
        t.__getattribute__("tm_mday"))
    picpath = 'h:\\ImageDownload\\%s\\%s' % (foldername,word.get()) # 下载到的本地目录
    # 路径不存在时创建一个
    if  os.path.exists(picpath):
        print('目标文件夹已存在')
    else :
        os.makedirs(picpath)

    for img in get_img:
        image=download(img)
        #以序号命名下载文件
        with open(picpath + '\\%s.jpg'%num,'wb') as fp:
            print('正在下载第%s张图片'%num)
            fp.write(image)
            print('第%s张图片下载完成' % num)
            num += 1
            if num>count:
                break
    num-=1
    print('本次共下载%s张图片,下载完成'%num)
    return
#汉语拼音
class PinYin(object):
    def __init__(self, dict_file='D:\Code\pythoncode\PhotoSpider\word.data'):
        self.word_dict = {}
        self.dict_file = dict_file
#加载拼音数据文件
    def load_word(self):
        if not os.path.exists(self.dict_file):
            raise IOError("NotFoundFile")

        with open(self.dict_file) as f_obj:
            for f_line in f_obj.readlines():
                try:
                    line = f_line.split('    ')
                    self.word_dict[line[0]] = line[1]
                except:
                    line = f_line.split('   ')
                    self.word_dict[line[0]] = line[1]

    def pinyin1(self, string=""):
        result = []

        for char in string:
            key = '%X' % ord(char)
            result.append(self.word_dict.get(key, char).split()[0][:-1].lower())

        return result


#百度图库编码转换
def change(c):
    c=c.upper()
    c=c.replace("\X","%")
    d=c[2:len(c)-1]
    print(d)
    return d

#打开目标文件夹
def view(word):
    picpath = 'h:\\ImageDownload'
    for parent, dirnames, filenames in os.walk(picpath):
    # 三个参数:分别返回1.父目录 2.所有文件夹名字(不含路径) 3.所有文件名字
        for dirname in dirnames:  # 输出文件夹信息
                if dirname==word.get():
                    os.startfile(picpath,'')

if __name__ == '__main__':

    root = Tk()
    root.title("Photo Spider")

    mainframe = ttk.Frame(root, padding="5 5 12 12")
    mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
    mainframe.columnconfigure(0, weight=1)
    mainframe.rowconfigure(0, weight=1)

    word = StringVar()

    # row:行 column:列
    ttk.Label(mainframe, text="请 输 入 图 片的 关 键 字").grid(column=1, row=1, sticky=W)
    feet_entry = ttk.Entry(mainframe, width=25, textvariable=word)
    feet_entry.grid(column=2, row=1, sticky=(W, E))
    #图片来源下拉选择框
    number = StringVar()
    ttk.Label(mainframe, text="请 选 择 图 片 来 源").grid(column=1, row=3, sticky=W)
    numberChosen = ttk.Combobox(mainframe, width=12, textvariable=number)
    # 设置下拉列表的值
    numberChosen['values'] = ('百度图片','千图网')
    # 设置其在界面中出现的位置  column代表列   row 代表行
    numberChosen.grid(column=2, row=3, sticky=(W, E))
    # 设置下拉列表默认显示的值,0为 numberChosen['values'] 的下标值
    numberChosen.current(0)
    #打印下拉框选项的角标
    print(numberChosen['values'].index(numberChosen.get()))

    # 数量下拉选择框
    num = StringVar()
    ttk.Label(mainframe, text="请 选 择 下 载 图 片 数 量").grid(column=1, row=4, sticky=W)
    numChosen = ttk.Combobox(mainframe, width=12, textvariable=num)
    # 设置下拉列表的值
    numChosen['values'] = (10,20,50)
    # 设置其在界面中出现的位置  column代表列   row 代表行
    numChosen.grid(column=2, row=4, sticky=(W, E))
    # 设置下拉列表默认显示的值,0为 numberChosen['values'] 的下标值
    numChosen.current(0)
  #按钮
    Button(mainframe, text="Download", width=12,command=lambda:getimg(word,num)).grid(column=1, row=5, sticky=W)
    Button(mainframe, text="View",width=12, command=lambda:view(word)).grid(column=3, row=5, sticky=W)
    #美化界面
    for child in mainframe.winfo_children(): child.grid_configure(padx=40, pady=40)
    feet_entry.focus()
    #回车键执行getimg
    root.bind('<Return>',getimg)
    root.mainloop()

附上汉语转拼音要用到的word.data(http://pan.baidu.com/s/1b1Fz9k),在自己电脑上运行时将该数据文件的路径替换代码中的文件路径即可。
本程序下载完并不能直接打开下载图片的那一层文件夹,只能打开程序所给的路径文件夹,希望广大朋友给点修改建议。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值