Функция, возвращающая себя вместо значения str - PullRequest
1 голос
/ 31 марта 2020

Я использую PyQt5 в сочетании с cfscrape и BeautifulSoup в попытке отобразить название дня ребенка в качестве метки. Тем не менее, функция, которую я использую, чтобы захватить и вернуть имя ребенка, возвращает себя вместо имени. Вот мой код:

import sys
import cfscrape
from bs4 import BeautifulSoup
from functools import partial
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QApplication

class Scraper():
    def getNameOfTheDay():
        spider = cfscrape.CloudflareScraper()

        with spider:
            nameData = spider.get("https://www.babynames.com/").content

            soup = BeautifulSoup(nameData, "lxml")
            nameContainer = soup.find("div", {"class": "notd-name"})
            name = nameContainer.text
            return name

class NameScraper(QMainWindow):
    def __init__(self):
        super(NameScraper, self).__init__()
        self.setWindowTitle("Name Scraper")
        self.setFixedSize(644, 591)

        self.nameScraperUI()

        font = QtGui.QFont()
        font.setFamily("Segoe UI")
        font.setPointSize(10)

    def nameScraperUI(self):
        self.nameOfTheDayLbl = QtWidgets.QLabel(self)
        self.nameOfTheDayLbl.setGeometry(50, 50, 300, 15)
        self.nameOfTheDayLbl.setText("Name of The Day")

        self.scrapeBtn = QtWidgets.QPushButton(self)
        self.scrapeBtn.setGeometry(QtCore.QRect(230, 500, 181, 41))
        self.scrapeBtn.setText("Scrape Names")
        self.scrapeBtn.setObjectName("pushButton")
        self.scrapeBtn.clicked.connect(partial(self.updateLbl, self.nameOfTheDayLbl, Scraper.getNameOfTheDay))

    def updateLbl(self, label, text):
        label.setText(str(text))

def window():
    app = QtWidgets.QApplication(sys.argv)
    mainWin = NameScraper()
    mainWin.show()
    sys.exit(app.exec_())

window()

1 Ответ

3 голосов
/ 31 марта 2020

Я не вижу необходимости использовать частичное, так как вы можете сделать следующее:

    self.scrapeBtn.setObjectName("pushButton")
    self.scrapeBtn.clicked.connect(self.updateLbl)

def updateLbl(self):
    self.nameOfTheDayLbl.setText(Scraper.getNameOfTheDay())

Но если вы все еще хотите использовать частичное, вам следует оценить функцию:

self.scrapeBtn.clicked.connect(partial(self.updateLbl, self.nameOfTheDayLbl, Scraper.getNameOfTheDay()))

Но даже в этом случае это приведет к ошибке, поскольку для этого требуется параметр, поэтому вы должны использовать декоратор @staticmethod:

class Scraper():
    @staticmethod
    def getNameOfTheDay():
        # ...

При предыдущем изменении все еще возникает проблема: GUI зависает, потому что задача скребка занимает много времени, поэтому, чтобы избежать этой проблемы, она должна быть реализована в другом потоке. Учитывая все вышеизложенное, решение выглядит следующим образом:

import sys
import threading

import cfscrape

from bs4 import BeautifulSoup

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QApplication


class Scraper:
    @staticmethod
    def getNameOfTheDay():
        spider = cfscrape.CloudflareScraper()

        with spider:
            nameData = spider.get("https://www.babynames.com/").content

            soup = BeautifulSoup(nameData, "lxml")
            nameContainer = soup.find("div", {"class": "notd-name"})
            name = nameContainer.text
            return name


class QScraper(QtCore.QObject):
    nameSignal = QtCore.pyqtSignal(str)

    def start(self):
        threading.Thread(target=self._execute, daemon=True).start()

    def _execute(self):
        self.nameSignal.emit(Scraper.getNameOfTheDay())


class NameScraper(QMainWindow):
    def __init__(self):
        super(NameScraper, self).__init__()
        self.setWindowTitle("Name Scraper")
        self.setFixedSize(644, 591)

        self.q_scrapper = QScraper()

        self.nameScraperUI()

        self.q_scrapper.nameSignal.connect(self.nameOfTheDayLbl.setText)

    def nameScraperUI(self):
        self.nameOfTheDayLbl = QtWidgets.QLabel(self)
        self.nameOfTheDayLbl.setGeometry(50, 50, 300, 15)
        self.nameOfTheDayLbl.setText("Name of The Day")

        self.scrapeBtn = QtWidgets.QPushButton(self)
        self.scrapeBtn.setGeometry(QtCore.QRect(230, 500, 181, 41))
        self.scrapeBtn.setText("Scrape Names")
        self.scrapeBtn.setObjectName("pushButton")
        self.scrapeBtn.clicked.connect(self.q_scrapper.start)


def window():
    app = QtWidgets.QApplication(sys.argv)
    mainWin = NameScraper()
    mainWin.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    window()

Примечание: Решение @dahanraz неверно, поскольку getNameOfTheDay() работает при создании GUI а не при нажатии кнопки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...