import requests
from lxml import etree
import os
import sys
from urllib.parse import quote # 对汉字进行URL编码,URL编码的方式是把需要编码的字符转化为 %xx 的形式
import tkinter as tk
import tkinter.messagebox
import threading # 使用线程可解决UI界面卡死问题
import time # 本项目主要使用time.sleep()进行延时
# import PythonMagick # 图片处理
class the_emoticon():
def __init__(self):
# 创建UI图形化界面
self.window = tk.Tk() # 创建最上层主窗口
# 将图片转换成ico格式
# self.logo = PythonMagick.Image('./logo.png')
# self.logo.sample('128x128')
# self.logo.write('./logo.ico')
# self.window.iconbitmap('./logo.ico')
self.window.title("表情包批量下载工具 - 黑客零") # 窗口标题
self.sw = (self.window.winfo_screenwidth() - 400) / 2 # 得到屏幕宽度
self.sh = (self.window.winfo_screenheight() - 150) / 2 # 得到屏幕高度
self.window.geometry("400x150+%d+%d" % (self.sw, self.sh)) # 窗口大小+窗口位置
self.window.resizable(0, 0) # 设置窗口大小不可缩放,防止用户调整尺寸
# 定义Label组件用于显示字体
self.tit = tk.Label(self.window, text="表情包官网:http://www.doutula.com/", font=("华文行楷", 14)).place(x=60, y=10)
self.tit1 = tk.Label(self.window, text="(平均一页可爬取12x6=72张表情包)", font=("华文行楷", 8)).place(x=100, y=30)
self.pages = tk.Label(self.window, text="表情包页数:", font=("微软雅黑", 10)).place(x=80, y=50)
self.majors = tk.Label(self.window, text="表情包主题:", font=("微软雅黑", 10)).place(x=80, y=80)
# 分别定义两个输入框(爬取页数,爬取主题)
self.var_page = tk.StringVar()
self.var_major = tk.StringVar()
self.entry_page = tk.Entry(self.window, textvariable=self.var_page)
self.entry_page.place(x=160, y=50)
self.entry_major = tk.Entry(self.window, textvariable=self.var_major)
self.entry_major.place(x=160, y=80)
# 按钮组件,点击触发函数(通过线程解决UI界面卡死问题)
self.button = tk.Button(self.window, text='开始爬取', font='15', command=lambda : self.thread_it(self.get_tar))
self.button.place(x=160, y=110)
self.window.mainloop() # 启动主窗口循环
# 使用线程解决UI界面卡死问题(要加入self,否则报错)
def thread_it(self, func, *args):
'''将耗时的操作函数打包进线程'''
# 创建
t = threading.Thread(target=func, args=args)
# 守护
t.setDaemon(True)
# 启动
t.start()
# 阻塞 -- 卡死界面
# t.join()
# 主要表情包获取函数
def get_tar(self):
# 获取表情包页数和主题
try:
xx = self.var_page.get()
x = int(xx)
y = self.var_major.get()
except:
# print("请输入规范内容!")
result = tkinter.messagebox.askokcancel(title='警告', message='请重新打开本软件并输入规范内容!')
self.button['command'] = result
sys.exit(0)
self.window.destroy()
# 首先在当前目录下创建文件夹"表情包"
path = f".\表情包\{y}"
isExists = os.path.exists(path)
if not isExists:
os.makedirs(path)
# 改变按钮状态
if self.button['text'] == '开始爬取':
self.button['text'] = '爬取中...'
self.button.config(state="disabled")
# 共爬取x页表情包
for i in range(x):
# 获取页面数据
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36'
}
url = "http://www.doutula.com/search?type=photo&more=1&keyword=" + quote(y) + "&page=" + str(i)
html = requests.get(url, headers=headers).text
# print(html)
# 解析出其中的表情包数据
html_xpath = etree.HTML(html)
# 如果是选取的是第一个div,可以将div[1]简写成div;选择src属性的超链接会改变,data-original才是真实超链接(应该是反爬虫机制)
imgs = html_xpath.xpath('//*[@class="container"]/div/div/div[2]/div/div/div/div/a/img/@data-original')
# print(imgs)
num = 0
# 保存表情包数据到文件夹中
for img in imgs:
num += 1
try:
res = requests.get(img, headers=headers).content
img_name = img.split('/')[-1].split('.')[-1] # 通过split()方法,根据/将字符串img分割开,并取出/分割的最后一部分字符串作名字
img_path = f"{path}\{y}{num}.{img_name}" # 构造路径地址
with open(img_path, 'wb') as files:
files.write(res)
# print(img.name + " ====> 保存成功!")
except:
pass # 爬取失败直接忽视
# print("表情包全部爬取完毕!")
# 改变按钮状态
if self.button['text'] == '爬取中...':
self.button['text'] = '爬取成功'
time.sleep(2)
self.button['text'] = '开始爬取'
self.button.config(state="normal")
if __name__ == '__main__':
the_emoticon()
源码
记得关注哦