python tk库打包后无效
本帖最后由 fff123123 于 2023-11-3 22:07 编辑使用tkiter和requests制作的ui小说爬取,在pycharm里面可以正常运行,点击按钮可以执行绑定事件,
但是打包后exe文件运行,点击搜索确认按钮无反应 即这个方法confirmation_search
文件结构
main.py
bin
tk_ui.py
requestsutils.py
yuan.json
main.py为程序入口,然后启动tk_ui.py界面,在tk_ui里面按钮绑定了requestsutils中的一个网络请求方法,没有使用多线程
请问是为什么,是只有tkiter这样吗,我之前使用pyqt5打包的没有问题
main.py文件
from bin.tk_ui import MyApp
def main():
app = MyApp()
app.mainloop()
if __name__ == '__main__':
main()
tk_ui.py文件
from tkinter import *
from tkinter import ttk, messagebox
import tkinter.font as tf
from . import requestutils
class MyApp(Tk):
"""继承Tk,创建自己的桌面应用程序类"""
def __init__(self):
"""构造函数"""
super().__init__()
self.title('Frame')
# self.iconbitmap('./bin/Tk.ico')
self.geometry('800x500')
# self.resizable(width=False, height=False)# 阻止Python GUI的大小调整
# 底界面
self.frame = Frame(self, bg='#90c0c0')
self.frame.pack(expand=True, fill=BOTH)
self.frame2 = Frame(self.frame)# 界面1
self.frame3 = Frame(self.frame)# 界面2
self.frame4 = Frame(self.frame)# 界面3
self.current_page = self.frame2
self.init_ui()
def init_ui(self):
"""初始化界面"""
# 书籍存储搜索结果的二维列表
self.result = list()
# 章节存储搜索结果的二维列表
self.result2 = list()
# 章节内容存储搜索结果的二维列表
self.result3 = list()
# 设置字体
ft = tf.Font(family="微软雅黑", size=10)
# frame1是frame的第1个子控件,从左向右布局,按钮所在的控件
frame1 = Frame(self.frame, bg='#f0f0f0')
frame1.pack(side=LEFT)
# 3个Button是frame2的子控件,自上而下布局
Button(frame1, text='书架', width=10, command=self.first_page).pack(padx=5, pady=5)# 切换为界面1
Button(frame1, text='搜索', width=10, command=self.second_page).pack(padx=5, pady=5)# 切换为界面2
Button(frame1, text='阅读', width=10, command=self.third_page).pack(padx=5, pady=5)# 切换为界面3
# 第一个界面ui
Label(self.frame2, text='界面1', bg='#90c0c0').grid(row=1, column=1, padx=10, pady=10)
# 第二个界面ui
# 顶部单独的一个frame
frame2_1 = Frame(self.frame3, bg='#90c0c0')
frame2_1.pack(side=TOP, fill="x")
self.combo_source_book = ttk.Combobox(frame2_1, values=("全本免费小说", "某点中文网"), state='readonly')
self.combo_source_book.current(1)# 选择第一个
self.combo_source_book.grid(row=0, column=1, padx=2, pady=2, sticky="nsew")
self.entry_book_name = Entry(frame2_1, width=30)
self.entry_book_name.grid(row=0, column=2, padx=2, pady=2, sticky="nsew")# 书名获得
Button(frame2_1, text='确认', width=12, command=self.confirmation_search). \
grid(row=0, column=3, padx=2, pady=2, sticky="nsew")# 搜索确认键
# 设置行和列的权重
frame2_1.grid_rowconfigure(0, weight=1)
frame2_1.grid_columnconfigure(0, weight=1)
frame2_1.grid_columnconfigure(1, weight=2)
frame2_1.grid_columnconfigure(2, weight=1)
# 搜索结果显示
self.lb_books_name = Listbox(self.frame3)
self.lb_books_name.pack(expand=True, side=TOP, fill=BOTH, padx=5, pady=5)
# 绑定双点击函数 获取具体章节 内容
self.lb_books_name.bind("<Double-Button-1>", lambda event: self.get_book(self.lb_books_name.curselection()))
# 绑定单击函数 提示具体信息
self.lb_books_name.bind("<<ListboxSelect>>",
lambda event: self.get_book_introduce(self.lb_books_name.curselection()))
# 底部 书籍具体信息显示
# 创建文本框
self.book_introduce = Text(self.frame3, height=1)
self.book_introduce.pack(expand=True, side=TOP, fill=BOTH, padx=5, pady=5)
# 第三个界面ui
frame3_1 = Frame(self.frame4, bg='#90c0c0')
frame3_1.grid(row=0, column=0, padx=2, pady=2, sticky="nsew")
frame3_2 = Frame(self.frame4, bg='#90c0c0')
frame3_2.grid(row=1, column=0, padx=2, pady=2, sticky="nsew")
self.frame4.grid_columnconfigure(0, weight=1)
self.frame4.grid_rowconfigure(0, weight=1)
self.frame4.grid_rowconfigure(1, weight=25)
# 第一个frame
self.frame3_1_name = StringVar()# 获取书名
Label(frame3_1, textvariable=self.frame3_1_name).grid(row=0, column=0, padx=2, pady=2, sticky="nsew")
Button(frame3_1, text="上一章").grid(row=0, column=1, padx=2, pady=2, sticky="nsew")
Button(frame3_1, text='下一章').grid(row=0, column=2, padx=2, pady=2, sticky="nsew")
# 设置行和列的权重
frame3_1.grid_rowconfigure(0, weight=1)
frame3_1.grid_columnconfigure(0, weight=3)
frame3_1.grid_columnconfigure(1, weight=1)
frame3_1.grid_columnconfigure(2, weight=1)
# 第二个frame
self.lb_chapter_name = Listbox(frame3_2)
# 绑定双点击函数 获取具体章节 内容
self.lb_chapter_name.bind("<Double-Button-1>",
lambda event: self.get_chapter_content(self.lb_chapter_name.curselection()))
# 多行文本
self.lb_chapter_info = Text(frame3_2, font=ft)
self.lb_chapter_name.grid(row=0, column=0, padx=2, sticky="nsew")
self.lb_chapter_info.grid(row=0, column=1, padx=2, sticky="nsew")
# 设置行和列的权重
frame3_2.grid_rowconfigure(0, weight=1)
frame3_2.grid_columnconfigure(0, weight=1)
frame3_2.grid_columnconfigure(1, weight=5)
# 默认显示界面1,并记录当前界面
self.current_page.pack(expand=True, side=LEFT, fill=BOTH, padx=5, pady=5)
# 书籍搜索确认键
def confirmation_search(self):
s1 = self.combo_source_book.current()# 书源
print("第" + str(s1) + "个书源")
s2 = self.entry_book_name.get()# 书名
# 检查 清除listbox框内的内容
numble = self.lb_books_name.size()
if numble != 0:
self.lb_books_name.delete(0, END)
if s2 != "":
# 根据书源搜索书
self.result = requestutils.requests_util(s2, s1, 0)
if self.result3 != '':
self.lb_books_name.insert(END, "成功")
else:
self.lb_books_name.insert(END, "失败")
print(self.result)
# 把搜索结果显示在listbox上
for item in self.result:
self.lb_books_name.insert(END, item[0] + "----" + item[1] + "\n\n")
else:
# 提示没有输入书名
messagebox.showinfo('提示', '没有输入书名')
# 具体书籍url 获取具体章节信息 章节内容
def get_book(self, index):
# 设置阅读界面的书名
s = self.entry_book_name.get()# 书名
self.frame3_1_name.set(s)
# 跳转到阅读界面
self.third_page()
for i in index:
# 获取书的url
# 获取书籍内容 /获取章节内容
s = self.result[-1]
# 网络请求获取章节信息
s1 = self.combo_source_book.current()# 书源
# 检查 清除listbox框内的内容
# 根据书源搜索具体书籍
self.result2 = requestutils.requests_util(s, s1, 1)
print(self.result2)
# 清除阅读界面的章节数据
self.lb_chapter_name.delete(0, END)
# 设置阅读界面的章节数据
for item in self.result2:
# 添加章节名
self.lb_chapter_name.insert(END, item[0])
break
# 获取章节内容
def get_chapter_content(self, index):
for i in index:
# 获取书的url
url = self.result2[-1]
# 网络请求获取章节信息
s1 = self.combo_source_book.current()# 书源
# 检查 清除listbox框内的内容
# 根据书源搜索具体书籍
self.result3 = requestutils.requests_util(url, -1, 2)
print(type(self.result3))
self.lb_chapter_info.delete(1.0, END)
self.lb_chapter_info.insert(END, self.result3)
# 获取书籍介绍
def get_book_introduce(self, index):
print(index)
for i in index:
# 显示书籍具体信息
self.book_introduce.config(state=NORMAL)
# 清除内容
self.book_introduce.delete("1.0", END)
self.book_introduce.insert("0.0",
self.result[0] + " " + self.result[1] + "\n\n" + self.result[2])
self.book_introduce.config(state=DISABLED)
break
# 跳转到第一个ui
def first_page(self):
if self.current_page != self.frame2:
self.current_page.pack_forget()# 取消显示当前界面,并不是销毁
self.current_page = self.frame2
self.current_page.pack(expand=True, side=LEFT, fill=BOTH, padx=5, pady=5)# 显示界面1
# 跳转到第二个ui
def second_page(self):
if self.current_page != self.frame3:
self.current_page.pack_forget()# 取消显示当前界面,并不是销毁
self.current_page = self.frame3
self.current_page.pack(expand=True, side=LEFT, fill=BOTH, padx=5, pady=5)# 显示界面2
# 跳转到第三个ui
def third_page(self):
if self.current_page != self.frame4:
self.current_page.pack_forget()# 取消显示当前界面,并不是销毁
self.current_page = self.frame4
self.current_page.pack(expand=True, side=LEFT, fill=BOTH, padx=5, pady=5)# 显示界面3
requestsutils.py文件
import json
import random
import time
import requests
from bs4 import BeautifulSoup
from lxml import etree
# 随机返回请求头user_agent
def getheader():
user_agent_list = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 "
"Safari/537.36 Edg/117.0.2045.47",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1"
]
return random.choice(user_agent_list)
# 读取json文件
def getMovieUrl():
with open("./bin/yuan.json", "r", encoding='utf-8') as file:
t = file.read()
link = json.loads(t)
return link
# 普通网络请求 书名/完整书url 书源选择(0/1) 搜索书(0)/搜索书的具体信息(1)
def requests_util(search, book_source_item, coeffcient):
# ip代{过}{滤}理
proxy = {
"http": "117.186.232.73:8080"
}
book_source_item = book_source_item + 1
# 读取json文件
item = getMovieUrl()
item = item
# 存储搜索结果的二维列表
result = list()
# 网络请求准备
name = item["bookSourceName"]
url = item["bookSourceUrl"]
search_url = item["search_url"]
chapter_search_url = item["chapter_search_url"]
headers = item["headers"]
rules = item["rules"]
rules_chapter = item["rules_chapter"]
headers['User-Agent'] = getheader()
# 搜索书
if coeffcient == 0:
# 需要拼接
search_url += search
print("书源名" + name, "书源网站" + url, "搜索网址" + search_url)
response = requests.get(url=search_url, headers=headers, proxies=proxy, timeout=20)
# 搜索具体书籍 章节
elif coeffcient == 1:
print("书源名" + name, "书源网站" + url, "搜索网址" + search)
response = requests.get(url=search, headers=headers, proxies=proxy, timeout=20)
# 搜索具体内容
elif coeffcient == 2:
print(name, "搜索网址" + search)
response = requests.get(url=search, headers=headers, proxies=proxy, timeout=20)
time.sleep(1)
# response.encoding = response.apparent_encoding# 设置编码,防止由于编码问题导致文字错乱
# print(response.text)# 查看请求到的内容
content = response.content.decode("utf-8")
soup = BeautifulSoup(content, "html.parser")
# print(soup.text)
if coeffcient == 0:
print("搜索书籍")
# 打印筛选结果
t1 = rules["basics"]
t2 = rules["book_name"]
t3 = rules["book_author"]
t4 = rules["info"]
t5 = rules["url_part"]
elements = soup.select(t1)
# print(elements)
for element in elements:
# 基本信息
s = list()
print("具体文本信息:书名 作者 介绍")
book_name = element.select_one(t2).text
book_author = element.select_one(t3).text
info = element.select_one(t4).text
s.append(book_name)
s.append(book_author)
s.append(info)
# url信息
url_part = element.select_one(t5).get("href")
spilt_after_url = url_part.split("book")[-1]
new_url = chapter_search_url + spilt_after_url
print("分割后字符串" + spilt_after_url)
s.append(new_url)
result.append(s)
# 设置只保持10个搜索的结果
if len(result) > 10:
break
# print(result)
return result
elif coeffcient == 1:
print("搜索章节")
# 返回 章节名 章节url
t1 = rules_chapter["basics"]
t2 = rules_chapter["part1"]
elements = soup.select(t1)
# print(elements)
for element in elements:
chapters = element.find_all(t2)
for chapter in chapters:
s = list()
name = chapter.text
part_url = chapter.get("href")
# 找有没有前缀 没有 有前缀 删掉com之前的内容
if "com" in part_url:
chapter_url = url + part_url.split("com", 1)[-1]
else:
chapter_url = url + part_url
# print(name)
# print(url)
s.append(name)
s.append(chapter_url)
result.append(s)
return result
elif coeffcient == 2:
print("搜索章节内容")
# 创建一个XPath解析器
parser = etree.HTMLParser()
tree = etree.HTML(content, parser=parser)
# search为url
# 某点的规则 find(www.qidian.com)
if "www.qidian.com" in search:
# 使用XPath选择器筛选页面数据
# 创建一个XPath解析器
parser = etree.HTMLParser()
tree = etree.HTML(content, parser=parser)
# 使用XPath选择器筛选页面数据
script_element = tree.xpath('//script[@id="vite-plugin-ssr_pageContext"]/text()')
json_data = script_element[0].strip()
data = json.loads(json_data)
value = data['pageContext']['pageProps']['pageData']['chapterInfo']['content'].replace("<p>", "\n")
print(value)
return value
# 全本的规则
elif "www.qbmfxs.com" in search:
# 使用XPath选择器筛选页面数据 str
value = tree.xpath("/html/body/div/div/div/div//p/text()")
print(value)
return value
这是main.spec文件
# -*- mode: python ; coding: utf-8 -*-
a = Analysis(
['main.py'],
pathex=['D:\\other_folders\\code_workplace\\read_book'],
binaries=[],
datas=[('D:\\other_folders\\code_workplace\\read_book\\bin\\requestutils.py','bin'),('D:\\other_folders\\code_workplace\\read_book\\bin\\tk_ui.py','bin'),('D:\\other_folders\\code_workplace\\read_book\\bin\\yuan.json','bin\\yuan.json')],
hiddenimports=['tkinter','requests'],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
noarchive=False,
)
pyz = PYZ(a.pure)
exe = EXE(
pyz,
a.scripts,
[],
exclude_binaries=True,
name='main',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=False,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
coll = COLLECT(
exe,
a.binaries,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name='main',
)
打包后exe执行后tk界面正常显示,但是按钮绑定事件没有反应 发了一大堆,感觉没说到重点啊{:301_1008:}
具体绑定的代码咋实现的?有没有对模块或程序做些其他处理?(我个人感觉是有的,不然整个hiddenimport还把主程序单独拉出来抽象一层干嘛) 连上帝都不让你看小说,还是007 不发问题的代码 上帝来了也不能帮你解决问题 我是在pycharm里面运行没有问题,只是打包后exe文件使用有问题 hrh123 发表于 2023-11-3 20:59
发了一大堆,感觉没说到重点啊
具体绑定的代码咋实现的?有没有对模块或程序做些其他处理?(我个 ...
hiddenimport我是在百度后说是可能没有导入模块,需要再次声明一下
页:
[1]