您必须在另一个线程中执行繁重的任务(请求+ BeautifulSoup),因为它们会阻塞 GUI 所在的主线程,从而阻止 GUI 正常工作,例如,通过冻结屏幕来体现这一点。在这种情况下,我将实现工作线程方法:
import re
import ssl
import sys
from functools import partial
import requests
from PyQt5.QtCore import QObject, QThread, QTimer, pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import QApplication, QDialog, QMessageBox
from bs4 import BeautifulSoup
from foo_module import Ui_Dialog
class ScrapeWorker(QObject):
started = pyqtSignal()
finished = pyqtSignal()
resultsChanged = pyqtSignal(str)
errorSignal = pyqtSignal(str)
@pyqtSlot(str)
def run(self, text):
self.started.emit()
sUrl = "https://removed.com/{}/p/?section=2&page=1".format(text)
try:
sr = requests.get(sUrl)
except Exception as e:
self.errorSignal.emit("error: {}".format(e))
self.finished.emit()
return
soup1 = BeautifulSoup(sr.text, "html.parser")
NumberOfPagesBlock = soup1.find_all("li", class_="text-gray")
if not NumberOfPagesBlock:
self.errorSignal.emit("Nothing Here")
else:
items = re.compile(r"[^\d.]+")
PagesCount = -(-items // 60)
for i in range(1, int(PagesCount + 1)):
itemsIdDs = soup1.find_all("div", class_="large-single-item")
for itemsIdD in itemsIdDs:
iUrl = "https://removed.com/{}/s".format(itemsIdDs.get("data-ean"))
r = requests.get(iUrl)
soup = BeautifulSoup(r.text, "html.parser")
seller = soup.find("div", id="productTrackingParams")
title = "{}- Title {}".format(ctr, seller.get("data-title"))
self.resultsChanged.emit(title)
self.finished.emit()
class MyForm(QDialog):
def __init__(self):
super().__init__()
self.ui = Ui_Dialog()
self.ui.setupUi(self)
self.ui.buttonOK.clicked.connect(self.searchAll)
thread = QThread(self)
thread.start()
self.m_worker = ScrapeWorker()
self.m_worker.moveToThread(thread)
self.m_worker.started.connect(self.onStarted)
self.m_worker.finished.connect(self.onFinished)
self.m_worker.resultsChanged.connect(self.onResultChanged)
self.m_worker.errorSignal.connect(self.onErrorSignal)
@pyqtSlot()
def searchAll(self):
sID = self.ui.txtSellerID.text()
wrapper = partial(self.m_worker.run, sID)
QTimer.singleShot(0, wrapper)
@pyqtSlot(str)
def onResultChanged(self, title):
self.ui.txtDetails.appendPlainText(title)
@pyqtSlot()
def onStarted(self):
self.ui.buttonOK.setEnabled(False)
@pyqtSlot()
def onFinished(self):
self.ui.buttonOK.setEnabled(True)
@pyqtSlot(str)
def onErrorSignal(self, message):
QMessageBox.about(self, "Warning", message)
if __name__ == "__main__":
app = QApplication(sys.argv)
w = MyForm()
w.show()
sys.exit(app.exec_())