|
|
@@ -2,6 +2,7 @@ import sys
|
|
|
import os
|
|
|
import time
|
|
|
import traceback
|
|
|
+import subprocess
|
|
|
import pandas as pd
|
|
|
from PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
|
|
|
QHBoxLayout, QLineEdit, QPushButton, QTextEdit,
|
|
|
@@ -76,6 +77,12 @@ class ScraperThread(QThread):
|
|
|
err = traceback.format_exc()
|
|
|
self.log.emit(f"<font color='red'>[错误] {str(e)}</font>")
|
|
|
self.finished.emit(err, scraper, duration)
|
|
|
+ finally:
|
|
|
+ if scraper:
|
|
|
+ try:
|
|
|
+ scraper.quit()
|
|
|
+ except Exception:
|
|
|
+ pass
|
|
|
|
|
|
class MainWindow(QMainWindow):
|
|
|
def __init__(self):
|
|
|
@@ -216,6 +223,11 @@ class MainWindow(QMainWindow):
|
|
|
self.thread.start()
|
|
|
|
|
|
def on_finished(self, err, scraper, duration):
|
|
|
+ if scraper:
|
|
|
+ try:
|
|
|
+ scraper.quit()
|
|
|
+ except Exception:
|
|
|
+ pass
|
|
|
self.search_btn.setEnabled(True)
|
|
|
self.count_spin.setEnabled(True)
|
|
|
if not err:
|
|
|
@@ -227,6 +239,29 @@ class MainWindow(QMainWindow):
|
|
|
except: pass
|
|
|
else: self.status_label.setText("异常终止")
|
|
|
|
|
|
+ def _kill_browser_processes(self):
|
|
|
+ """结束可能残留的 Chrome/ChromeDriver,避免占用 dist 目录导致无法删除或打包"""
|
|
|
+ if os.name != "nt":
|
|
|
+ return
|
|
|
+ for proc in ("chrome.exe", "chromedriver.exe"):
|
|
|
+ try:
|
|
|
+ subprocess.run(
|
|
|
+ ["taskkill", "/F", "/IM", proc, "/T"],
|
|
|
+ capture_output=True,
|
|
|
+ timeout=5,
|
|
|
+ )
|
|
|
+ except Exception:
|
|
|
+ pass
|
|
|
+
|
|
|
+ def closeEvent(self, event):
|
|
|
+ if hasattr(self, "thread") and self.thread.isRunning():
|
|
|
+ self.thread.requestInterruption()
|
|
|
+ if not self.thread.wait(5000):
|
|
|
+ self.thread.terminate()
|
|
|
+ self.thread.wait(2000)
|
|
|
+ self._kill_browser_processes()
|
|
|
+ event.accept()
|
|
|
+
|
|
|
if __name__ == "__main__":
|
|
|
app = QApplication(sys.argv)
|
|
|
win = MainWindow()
|