【问题标题】:Google search suggestion in PyQt5PyQt5 中的谷歌搜索建议
【发布时间】:2021-03-04 12:40:13
【问题描述】:

我为使用 pyqt5 和 python 构建的简单浏览器构建了一个谷歌搜索建议完成器。代码如下。

    self.url_bar = QLineEdit()
    
    self.url_bar.textChanged.connect(self.suggest)

def suggest(self):

    suggestlist =[]

    term = self.url_bar.text()
    if not (validators.url(term) and term != '') :
        url = f"http://toolbarqueries.google.com/complete/search?q={term}&output=toolbar&hl=en"

        suggestions = requests.get(url)
        suggestions = ET.fromstring(suggestions.content)
        for data in suggestions.iter('suggestion'):
            suggestlist.append(data.attrib['data'])
    

    suggester = QCompleter(suggestlist)
    self.url_bar.setCompleter(suggester)

这会正确生成建议,但浏览器会意外关闭。请帮帮我。

【问题讨论】:

  • 您不能为此使用请求,因为它会阻止程序,直到它得到回复。此外,发送每个文本更改的请求不是一个好主意,因为您将发送每个字符类型的请求。使用 singleShot QTimer,它在超时时使用 QThread(或者更好的 QNetworkAccessManager)发送请求,并将textChanged 连接到计时器的开始处。

标签: python python-3.x pyqt5 qlineedit qcompleter


【解决方案1】:

根据我之前的帖子并进行一些修改,您可以获得以下解决方案。我不使用请求,因为如果请求时间过长,它可能会阻塞事件循环。

import xml.etree.ElementTree as ET

from PyQt5 import QtCore, QtGui, QtWidgets, QtNetwork


class SuggestionModel(QtGui.QStandardItemModel):
    finished = QtCore.pyqtSignal()
    error = QtCore.pyqtSignal(str)

    def __init__(self, parent=None):
        super(SuggestionModel, self).__init__(parent)
        self._manager = QtNetwork.QNetworkAccessManager(self)
        self._reply = None

    @QtCore.pyqtSlot(str)
    def search(self, text):
        self.clear()
        if self._reply is not None:
            self._reply.abort()
        if text:
            r = self.create_request(text)
            self._reply = self._manager.get(r)
            self._reply.finished.connect(self.on_finished)
        loop = QtCore.QEventLoop()
        self.finished.connect(loop.quit)
        loop.exec_()

    def create_request(self, text):
        url = QtCore.QUrl("http://toolbarqueries.google.com/complete/search")
        query = QtCore.QUrlQuery()
        query.addQueryItem("q", text)
        query.addQueryItem("output", "toolbar")
        query.addQueryItem("hl", "en")
        url.setQuery(query)
        request = QtNetwork.QNetworkRequest(url)
        return request

    @QtCore.pyqtSlot()
    def on_finished(self):
        reply = self.sender()
        if reply.error() == QtNetwork.QNetworkReply.NoError:
            content = reply.readAll().data()
            suggestions = ET.fromstring(content)
            for data in suggestions.iter("suggestion"):
                suggestion = data.attrib["data"]
                self.appendRow(QtGui.QStandardItem(suggestion))
            self.error.emit("")
        elif reply.error() != QtNetwork.QNetworkReply.OperationCanceledError:
            self.error.emit(reply.errorString())
        else:
            self.error.emit("")
        self.finished.emit()
        reply.deleteLater()
        self._reply = None


class Completer(QtWidgets.QCompleter):
    def splitPath(self, path):
        self.model().search(path)
        return super(Completer, self).splitPath(path)


class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)
        self._model = SuggestionModel(self)
        completer = Completer(self, caseSensitivity=QtCore.Qt.CaseInsensitive)
        completer.setModel(self._model)
        lineedit = QtWidgets.QLineEdit()
        lineedit.setCompleter(completer)
        label = QtWidgets.QLabel()
        self._model.error.connect(label.setText)
        lay = QtWidgets.QFormLayout(self)
        lay.addRow("Location: ", lineedit)
        lay.addRow("Error: ", label)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.resize(400, w.sizeHint().height())
    w.show()
    sys.exit(app.exec_())

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-01
    • 1970-01-01
    • 2012-11-10
    • 2011-04-18
    • 2010-09-25
    • 2013-01-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多