【问题标题】:Is it possible to click inside a self made web app?是否可以在自制的网络应用程序中单击?
【发布时间】:2019-09-20 02:52:23
【问题描述】:

我创建了一个 PyQt5 网络应用程序,它使用以下代码导航到 https://www.google.com/

from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtWebEngineWidgets import *

import sys

class MainWindow(QMainWindow):

    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        self.setWindowTitle("My Window")

        self.browser = QWebEngineView()
        self.browser.setUrl( QUrl("www.google.com") )
        self.setCentralWidget(self.browse) 

app = QApplication(sys.argv)

window = MainWindow()
window.show()

app.exec()

这个想法是我想在应用程序内部操作点击,因此在谷歌网站上,例如:将鼠标移动到某些位置(x,y),而不像 pyautogui 那样影响 PC 本身,这意味着我可以运行在网络应用程序内随机点击的代码,而我可以在 PC 上执行正常操作,而不会影响鼠标。

我很高兴知道这是否可行。如果是,如何?

注意:我没有真正的python经验

【问题讨论】:

  • 虽然不完全符合您的要求,但您也可以让 selenium 代码在 vm 中运行。这会释放你的鼠标。
  • @mrfreester OP 需要的是能够模拟使用 QWebEngineView 制作的自定义浏览器中的点击事件(和其他事件)

标签: python pyqt pyqt5 qtwebengine qwebengineview


【解决方案1】:

您可以通过发送 QMouseEvent 来模拟点击,在 QWebEngineView 的情况下,点击应该发送到一个内部小部件,该小部件是私有 Qt API 的一部分,但可以通过一个小逻辑访问:使用 findChildren 和 QMetaObject。

在以下示例中,单击位置 400、200,在我的例子中是一个 google 横幅,将打开相应的信息。

import sys
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.setWindowTitle("My Window")

        self.browser = QtWebEngineWidgets.QWebEngineView()
        self.browser.setUrl(QtCore.QUrl("https://www.google.com/"))
        self.setCentralWidget(self.browser)
        self.browser.loadFinished.connect(self.on_loadFinished)

    @QtCore.pyqtSlot(bool)
    def on_loadFinished(self, ok):
        if not ok:
            return
        w = None
        for child in self.browser.findChildren(QtWidgets.QWidget):
            if (
                child.metaObject().className()
                == "QtWebEngineCore::RenderWidgetHostViewQtDelegateWidget"
            ):
                w = child
                break
        if w is not None:
            self.emulate_click(w, QtCore.QPoint(400, 200))

    def emulate_click(self, widget, pos):
        event_press = QtGui.QMouseEvent(
            QtCore.QEvent.MouseButtonPress,
            pos,
            QtCore.Qt.LeftButton,
            QtCore.Qt.LeftButton,
            QtCore.Qt.NoModifier,
        )
        QtCore.QCoreApplication.postEvent(widget, event_press)
        event_release = QtGui.QMouseEvent(
            QtCore.QEvent.MouseButtonRelease,
            pos,
            QtCore.Qt.LeftButton,
            QtCore.Qt.LeftButton,
            QtCore.Qt.NoModifier,
        )
        QtCore.QCoreApplication.postEvent(widget, event_release)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.resize(640, 480)
    w.show()
    sys.exit(app.exec_())

如果您有更多信息,例如 id 或 xpath,您可以使用 javascript 点击:

import sys
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.setWindowTitle("My Window")

        self.browser = QtWebEngineWidgets.QWebEngineView()
        self.browser.setUrl(QtCore.QUrl("https://www.google.com/"))
        self.setCentralWidget(self.browser)
        self.browser.loadFinished.connect(self.on_loadFinished)

    @QtCore.pyqtSlot(bool)
    def on_loadFinished(self, ok):
        if not ok:
            return
        xpath = r"//body[@id='gsr']/div[@id='viewport']/div[@id='main']/span[@id='body']/center/div[@id='lga']/div[@id='hplogo']/a/img[1]"
        s = (
            """
            (function() {
                var banner = document.evaluate("%s", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
                banner.click()
            })()"""
            % xpath
        )
        self.browser.page().runJavaScript(s)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.resize(640, 480)
    w.show()
    sys.exit(app.exec_())

【讨论】:

    【解决方案2】:

    除非它是一个嵌入式应用程序,否则您始终可以解析 html、搜索按钮并通过请求它要走的路径或通过 javascript 解析器“单击”按钮。

    在代码 api 之后看起来像

    parsed_response.find(my_button).click()
    

    如果你不坚持自己写,已经有一个了,selenium

    举个小例子

    from selenium import webdriver
    from selenium.webdriver.common.keys import Keys
    
    driver = webdriver.Chrome()
    driver.get("www.website.com")
    login_input = driver.find_element_by_id(id)
    login_input.send_keys(my_login)
    login_input.send_keys(Keys.ENTER)
    # Or you can do something like
    # submit_button = driver.find_element_by_id(submitbutton)
    # submit_button.click()
    

    硒的力量是巨大的,但是当我回答有关网络抓取的问题时,我总是将其添加为注释。在您的机器人实际使用该网站之前,请务必检查 /robots.txt。

    【讨论】:

      猜你喜欢
      • 2023-01-14
      • 1970-01-01
      • 1970-01-01
      • 2019-07-11
      • 1970-01-01
      • 2012-11-10
      • 1970-01-01
      • 2018-02-15
      • 1970-01-01
      相关资源
      最近更新 更多