一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第30天,点击查看活动详情。
写在前面
对于一个程序猿来说,或者对于一个Python程序猿来说,你写的爬虫最后是一个python文件,传播起来毫无问题,但是你想让更多的人使用你的爬虫程序,让你的程序普适性更强,你就不能给用户一个Python文件,然后告诉他,你先安装Python环境,在扩展包,在不拉不拉,我想这样你的程序也不会有人使用了
接下来,我们将用5篇左右的博客,让大家把爬虫写的更加普遍化,后续的代码,不一定是最优的代码写法,逻辑也不一定是最优秀的代码,更多的是为了让大家将自己的爬虫“发扬光大”,让你身边的人用上你写的爬虫,当然,具备一点点的扩展性就更好了
桌面程序
没错,我们一上来就要写的是桌面程序,也就是.exe程序,该功能用到了一个Python GUI库tkinter
我们先简单的把他过一遍,当然,作为爬虫百例教程,即使学习tkinter
也要来个跟爬虫相关的东西,今天我们就实现一个最简单的,输入任意一个网页,点击下载,下载里面所有的图片
图形用户界面(Graphical User Interface,简称 GUI)
原型图如下(原型用AXURE画的,见谅~)
画出程序的界面来
由于前段时间做了一年左右的自考相关课程,每天搞C++,操作系统,数据结构,头大了,Python环境都找不到啦~所以,需要简单配置一下Python的可用环境
pip list
确定pip可用
python
3.7 版本
OK,毫无问题,赖以谋生的本领还在,接下来,继续吧
对于tkinter
,可能比较陌生,不过还好,它就是一个Python模块,上手比较容易,不会也没事,打开一个官网文档,扫两眼,看看即可 docs.python.org/zh-cn/3/lib…,为何扫两眼即可,因为这文档好啊,对于初学者,压根不知道说的是啥?
有人肯定问,为什么这么多GUI库,要选择 tkinter 呢?还不是因为这是Python自带的,而且还简单... ,当然很多人也在吐槽说不好用,其实作为学习无所谓的,everything is right,况且 tkinter
也没有那么烂,整体还是不错的。
在控制台运行命令python -m tkinter
如下图所示,表示没啥毛病,可以撸代码了
上来先写两行代码练练手,恩,上头了,还是写Python有意思
import tkinter
# from tkinter import Tk
# 创建主窗口
win = tkinter.Tk()
# 设置标题
win.title("抓图小程序")
# 进入消息循环,可以写控件
win.mainloop()
你看当这个窗口实现了,按照我的常规套路,这个项目其实已经做完了,哈哈
接下来,窗口有点小,调调
from tkinter import Tk
# 创建主窗口
win = Tk()
# 设置标题
win.title("抓图小程序")
win.geometry('500x300') # 注意这个x是字母x
# 进入消息循环,可以写控件
win.mainloop()
运行结果如下,为何画两条直线呢?这就有点门道了,注意看win.geometry('500x300')
这句代码,如果我修改一下,调整成下述内容
win.geometey('500x300+200+400') # 参照下图
![python爬虫百例教程 python爬虫百例教程](img-blog.csdnimg.cn/20200320232… =500x) ![python爬虫百例教程 python爬虫百例教程](img-blog.csdnimg.cn/20200320233… =500x) 具体内容不解释,自己猜
接下来,我们让其实现居中显示在屏幕中央,逻辑比较简单,就是获取分辨率,然后加减乘除一通计算即可
from tkinter import Tk
# 创建主窗口
win = Tk()
# 设置标题
win.title("抓图小程序")
# 窗体大小设置
width = 500
height = 400
# 获取屏幕分辨率
screen_width = win.winfo_screenwidth()
screen_height = win.winfo_screenheight()
position = f"{width}x{height}+{(screen_width-width)/2:.0f}+{(screen_height-height)/2:.0f}"
win.geometry(position)
# win.geometry('500x300+200+400')
# 进入消息循环,可以写控件
win.mainloop()
绘制输入框和按钮
绘制UI的时候,需要学习和补充的知识点有控件的简单用法,控件就是指的按钮,文本框等,控件的布局,代码如下
#from tkinter import Tk
import tkinter as tk
# 创建主窗口
win = tk.Tk()
# 设置标题
win.title("抓图小程序")
# 窗体大小设置
width = 500
height = 400
# 获取屏幕分辨率
screen_width = win.winfo_screenwidth()
screen_height = win.winfo_screenheight()
position = f"{width}x{height}+{(screen_width-width)/2:.0f}+{(screen_height-height)/2:.0f}"
win.geometry(position)
# win.geometry('500x300+200+400')
# 进入消息循环,可以写控件
# 创建提示文本
lb = tk.Label(win, text='请输入网址:')
# 创建文本框
entry = tk.Entry(win,width=30) # width 设置输入框的宽度,以字符为单位,默认值是20
# 创建按钮
btn = tk.Button(win,text = '分析下载')
# 创建一个多行文本框
t = tk.Text(win, width=60,height=20)
lb.grid(row=1,column=0,padx=10,pady=20)
entry.grid(row=1,column=1,pady=20)
btn.grid(row=1,column=2,padx=10,pady=20)
t.grid(row=2,column=0,padx=20,columnspan=3)
win.mainloop()
以上代码出现的效果图如下 tkinter基于以上代码的简单入门,说明如下
tk.Label
,tk.Entry
,tk.Button
,tk.Text
对应的是各种不同的组建,他们都是函数,都包含很多参数,拿一个举例子如下
tk.Label(win,text='提示文字:',font=('黑体',20),bg='black',width=10,height=8) 其中第一个参数win,表示tk对象,这个无歧义 text 表示Label显示的文字 font 字体和大小元组 width 宽度,字符为单位 height 高度,字符为单位,啥叫字符单位,很简单,10个表示有10个字符
接下来是一段添加控件和布局相关的代码
lb.grid(row=1,column=0,padx=10,pady=20)
entry.grid(row=1,column=1,pady=20)
btn.grid(row=1,column=2,padx=10,pady=20)
t.grid(row=2,column=0,padx=20,columnspan=3)
在tkinter中有三种控件布局方式
- place
- pack
- grid
每种布局都有独特的代码写法,以下我简单进行说明,如果深挖,建议搜索引擎走起,好好搞搞
- pack 布局
参数如下 after: 将组件置于其他组件之后; before: 将组件置于其他组件之前; anchor: 组件的对齐方式,顶对齐'n',底对齐's',左'w',右'e' side: 组件在主窗口的位置,可以为'top','bottom','left','right'(使用时tkinter.TOP,tkinter.LEFT); fill: 填充方式 (Y,垂直,X,水平,BOTH,水平+垂直),是否在某个方向充满窗口 expand:1可扩展,0不可扩展,代表控件是否会随窗口缩放
看一下效果,然后实操的时候,你应该会碰到更多的坑,碰到想办法解决即可,编程的乐趣就是与BUG斗法!
from tkinter import *
root = Tk()
w = Label(root, text="red", bg="red", fg="white")
w.pack(padx=5, pady=10, side=LEFT)
w = Label(root, text="green", bg="green", fg="black")
w.pack(padx=5, pady=20, side=LEFT)
w = Label(root, text="blue", bg="blue", fg="white")
w.pack(padx=5, pady=20, side=LEFT)
mainloop()
2. place布局
这个比较简单了,就是按照坐标系进行布局,坐标系原点是窗口的左上角 anchor: 组件对齐方式;n, ne, e, se, s, sw, w, nw, or center ; ('n'==N) x: 组件左上角的x坐标; y: 组件左上角的y坐标; relx: 组件左上角相对于窗口的x坐标,应为0-1之间的小数;图形位置相对窗口变化 rely: 组件左上角相对于窗口的y坐标,应为0-1之间的小数; width: 组件的宽度; heitht: 组件的高度; relwidth: 组件相对于窗口的宽度,0-1之间的小数,图形宽度相对窗口变化; relheight: 组件相对于窗口的高度,0-1之间的小数;
- grid表格布局
该布局方式类似HTML中的DIV+CSS布局,作为一个老前端工程师,我比较喜欢这个布局方式,不过对初学者来说,不是很友好 column: 组件所在的列起始位置;
columnspan: 组件的列宽;跨列数 row:组件所在的行起始位置; rowspan: 组件的行宽;rowspam=3 跨3行 sticky:对齐方式:NSEW(北南东西)上下左右
padx、pady x方向间距、y方向间距(padx=5)
如果你英语底子不错,下面的三个文章,可以好好读读
effbot.org/tkinterbook…
effbot.org/tkinterbook…
effbot.org/tkinterbook…
触发按钮事件
布局完毕,下面实现点击按钮,获取文本框中输入的网址
首先在按钮声明的函数中添加新的参数
btn = tk.Button(win,text = '分析下载', command=down_img)
command 绑定触发函数
获取本文框内容
# 事件函数
def down_img():
# print("hello world")
# 获取文本框内容
url = entry.get()
analyse(url)
当你写到这里之后,剩下的只是爬虫和页面数据显示的问题了。
补全爬虫代码
按照拿到链接获取代码的方式,我们把代码补全,当然这个地方只做最基本的演示,没有做异步调用等功能,后续我们在逐步完善
爬虫代码补充完毕之后,代码长成下面的样子,下载网页的链接,我使用的是
https://cn.chinadaily.com.cn/a/202003/24/WS5e79839aa3107bb6b57a8652.html
#from tkinter import Tk
import tkinter as tk
import requests
import re
import time
# 创建主窗口
win = tk.Tk()
# 设置标题
win.title("抓图小程序")
# 窗体大小设置
width = 500
height = 400
# 获取屏幕分辨率
screen_width = win.winfo_screenwidth()
screen_height = win.winfo_screenheight()
position = f"{width}x{height}+{(screen_width-width)/2:.0f}+{(screen_height-height)/2:.0f}"
win.geometry(position)
# win.geometry('500x300+200+400')
# 进入消息循环,可以写控件
# 通用页面headers
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36",
"Referer":"https://img3.chinadaily.com.cn"
}
# 创建提示文本
lb = tk.Label(win, text='请输入网址:')
# 创建文本框
entry = tk.Entry(win,width=30) # width 设置输入框的宽度,以字符为单位,默认值是20
# 创建一个多行文本框
t = tk.Text(win, width=60,height=20)
# 下载图片
def save_img(img):
#t.insert("insert", f"下载中\n")
# 拼接URL
img = img if img.find('http')==0 else "http:"+img
try:
response = requests.get(img,headers=headers)
ctx = response.content
with open(f'./{time.time()}.jpg', 'wb') as f:
f.write(ctx)
except Exception as e:
print(e.args)
# 分析网页图片清单
def analyse(url):
resp = requests.get(url,headers=headers)
content = resp.text # 获取到网页内容
#print(content)
imgs = re.findall('img src="(.*?)"', content)
# 界面展示获取到的图片数量
t.insert("insert", f"获取到{len(imgs)}张图片\n")
t.insert("insert", f"开始下载图片...\n")
for img in imgs:
save_img(img)
t.insert("insert", f"下载完毕\n")
# 事件函数
def down_img():
# print("hello world")
# 获取文本框内容
url = entry.get()
analyse(url)
# 创建按钮
btn = tk.Button(win,text = '分析下载', command = down_img)
lb.grid(row=1,column=0,padx=10,pady=20)
entry.grid(row=1,column=1,pady=20)
btn.grid(row=1,column=2,padx=10,pady=20)
t.grid(row=2,column=0,padx=20,columnspan=3)
win.mainloop()
假如前面的博客你是一篇一篇看到这里来的,那么这段代码是非常简单的,就不在做过多的说明。 关于tkinter里面涉及的一个点就是多行文本框插入文本,这个随意百度一下很多内容。
完善软件界面
添加软件运行图标
现在这个软件已经基本已经成型,修改一下左上角的软件图标,这个地方一般用.ico图标
你可以打开 www.easyicon.net/language.en…
找一个你喜欢的图标,记得下载ico图标
代码也非常简单,把下载好的ico图标放置到根目录
win.iconbitmap('./spider.ico')
剩余的两种方法,不在涉及,可自行检索
iconphoto()
,tk.call()
打包成exe程序,用来分享
接下来通过 pip install pyinstaller 安装一下 打包程序,然后通过下面的命令生成exe程序 注意打包的时候,如果程序中设置了软件图标,那么打包的时候,需要调整的代码较多,这个我们后续在讨论 为了打包便携,我们删除图标设置部分代码,这部分没有展开,记得安装了 pip install pyinstaller 之后,我们还是在 Scripts文件夹里面进行的操作
pyinstaller -F D:\python100\newsimg.py --noconsole
打包之后,如下
写在后面
本篇博客,主要是给你一个非常非常简单的小案例,用于将自己的python爬虫进行打包,后续博客中,我们还将顺着这条思路走下去。
happy ending ...