fff123123 发表于 2023-11-3 19:26

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',
)






fff123123 发表于 2023-11-3 19:27

打包后exe执行后tk界面正常显示,但是按钮绑定事件没有反应

hrh123 发表于 2023-11-3 20:59

发了一大堆,感觉没说到重点啊{:301_1008:}
具体绑定的代码咋实现的?有没有对模块或程序做些其他处理?(我个人感觉是有的,不然整个hiddenimport还把主程序单独拉出来抽象一层干嘛)

sai609 发表于 2023-11-3 21:40

连上帝都不让你看小说,还是007

rogabet 发表于 2023-11-3 21:46

yang4384 发表于 2023-11-3 22:00

不发问题的代码 上帝来了也不能帮你解决问题

fff123123 发表于 2023-11-3 22:08

我是在pycharm里面运行没有问题,只是打包后exe文件使用有问题

fff123123 发表于 2023-11-3 22:13

hrh123 发表于 2023-11-3 20:59
发了一大堆,感觉没说到重点啊
具体绑定的代码咋实现的?有没有对模块或程序做些其他处理?(我个 ...

hiddenimport我是在百度后说是可能没有导入模块,需要再次声明一下
页: [1]
查看完整版本: python tk库打包后无效