On the realization of automatic Operation by Pyqt5

with the help of Li Yi"s PyQt5 embedded browser injecting Javascript scripts to automate operations , I have now completed the automation of low-cost airlines, but now I have encountered several problems:

  1. after I complete the order, such as entering the last page, and determine that the page url is / BookFlight/Wait, how can I pass it to my app to shut it down automatically? Or how to catch an exception along the way (such as when a CAPTCHA pops up)
  2. how to agent IP for Pyqt5"s embedded browser
  3. when I am encapsulating the code to flask, how to pass the parameters in JS? there will be an error when I use format or% S, because there are "{}" and "[]"
  4. in the js code.

I hope my doubts can be answered

the current Python code is as follows:

-sharp 
-sharp -*- coding: utf-8 -*-
""" PyQt5  Javascript """
import os
import sys
from datetime import datetime

from PyQt5.QtWidgets import (
    QWidget, QApplication, QVBoxLayout, QHBoxLayout,
    QDesktopWidget, QTextEdit, QLabel, QLineEdit, QPushButton,
    QFileDialog, QProgressBar,
)
from PyQt5.QtCore import QUrl, pyqtSlot
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEngineProfile, QWebEngineScript, QWebEnginePage


class Browser(QWidget):

    def __init__(self):
        super().__init__()
        self.init_ui()

        -sharp 
        self.profile = QWebEngineProfile.defaultProfile()
        self.script = QWebEngineScript()
        self.prepare_script()

    def init_ui(self):
        self.webView = QWebEngineView()

        self.logEdit = QTextEdit()
        self.logEdit.setFixedHeight(100)

        self.addrEdit = QLineEdit()
        self.addrEdit.returnPressed.connect(self.load_url)
        self.webView.urlChanged.connect(
            lambda i: self.addrEdit.setText(i.toDisplayString()))

        self.jsEdit = QLineEdit()
        self.jsEdit.setText("TR.js")

        loadUrlBtn = QPushButton("")
        loadUrlBtn.clicked.connect(self.load_url)

        chooseJsBtn = QPushButton("")
        chooseJsBtn.clicked.connect(self.choose_js_file)

        -sharp /
        top = QWidget()
        top.setFixedHeight(80)
        topBox = QVBoxLayout(top)
        topBox.setSpacing(0)
        topBox.setContentsMargins(5, 0, 0, 5)

        progBar = QProgressBar()
        progBox = QHBoxLayout()
        progBox.addWidget(progBar)
        topBox.addLayout(progBox)

        naviBox = QHBoxLayout()
        naviBox.addWidget(QLabel(""))
        naviBox.addWidget(self.addrEdit)
        naviBox.addWidget(loadUrlBtn)
        topBox.addLayout(naviBox)

        naviBox = QHBoxLayout()
        naviBox.addWidget(QLabel(""))
        naviBox.addWidget(self.jsEdit)
        naviBox.addWidget(chooseJsBtn)
        topBox.addLayout(naviBox)

        self.webView.loadProgress.connect(progBar.setValue)

        -sharp 
        layout = QVBoxLayout(self)
        layout.addWidget(self.webView)
        layout.addWidget(top)
        layout.addWidget(self.logEdit)

        self.show()
        self.resize(1024, 900)
        self.center()

    def center(self):
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    @pyqtSlot()
    def load_url(self):
        url = self.addrEdit.text().strip()
        if not url.lower().startswith("http://") \
                and not url.lower().startswith("https://"):
            url = "http://{}".format(url)
        self.load(url)

    @pyqtSlot()
    def choose_js_file(self):
        f, _ = QFileDialog.getOpenFileName(filter="Javascript files(*.js)")
        if os.path.isfile(f):
            self.jsEdit.setText(f)
            self.prepare_script()

    def prepare_script(self):
        path = self.jsEdit.text().strip()
        if not os.path.isfile(path):
            self.log("invalid js path")
            return

        self.profile.scripts().remove(self.script)
        with open(path, "r", encoding="utf-8") as f:
            self.script.setSourceCode(f.read())
        self.profile.scripts().insert(self.script)
        self.log("injected js ready")

    def log(self, msg, *args, **kwargs):
        m = msg.format(*args, **kwargs)
        self.logEdit.append("{} {}".format(
            datetime.now().strftime("%H:%M:%S"), m))

    def load(self, url):
        self.log(f"loading {url}")
        self.addrEdit.setText(url)
        self.webView.load(QUrl(url))


if __name__ == "__main__":
    app = QApplication(sys.argv)
    b = Browser()
    b.load("http://www.flyscoot.com/zh")
    sys.exit(app.exec_())

the current js code is as follows:

// 
function handle(path) {
    // 
    if (path == "/zh") {
        document.getElementsByClassName("radio-inline")[1].click();
        document.getElementById("oneway_from").value = " (CAN)";
        document.getElementById("oneway_to").value = " (SIN)";
        document.getElementById("oneway_departuredate").value = "20181020";
        document.getElementsByClassName("btn--booking")[1].click();
        return;
    }

    // 
    if (path == "/Book/Flight") {
        document.getElementsByClassName("price--sale")[0].click();
        document.getElementsByClassName("heading-4")[0].click();
        document.getElementsByClassName("btn-submit")[0].click();
        return;
    }

    // 
    if (path == "/BookFlight/Passengers") {
        // document.getElementsByClassName("fname1")[0].value = "";
        document.getElementById("selecttitle1").value="MR";
        document.getElementById("revPassengersInput_PassengerInfantModels_PassengersInfo_0__First").value = "tom";
        document.getElementById("revPassengersInput_PassengerInfantModels_PassengersInfo_0__Last").value = "wang";
        document.getElementById("revPassengersInput_PassengerInfantModels_PassengersInfo_0__DayOfBirth").value = "12";
        document.getElementById("revPassengersInput_PassengerInfantModels_PassengersInfo_0__MonthOfBirth").value = "12";
        document.getElementById("revPassengersInput_PassengerInfantModels_PassengersInfo_0__YearOfBirth").value = "1995";
        document.getElementById("revPassengersInput_PassengerInfantModels_PassengersInfo_0__Nationality").value = "CN";
        document.getElementsByClassName("radio-inline")[4].click();
        document.getElementsByClassName("btn-submit")[0].click();
    }
    if (path == "/BookFlight/Seats") {
        document.getElementById("nextFlightButton").click();
    }
    if (path == "/BookFlight/AddOns") {
        document.getElementsByClassName("btn-submit")[0].click();
    }
    if (path == "/BookFlight/Payment") {
        /*! jQuery v3.2.1 | (c) JS Foundation and other contributors | jquery.org/license */ 
        // jquery 

        document.getElementById("revContactInput_WorkPhone_Number").value="13578978541";
        document.getElementById("emailContact").value="wc110302@126.com";
        document.getElementsByTagName("input")[54].value="wc110302@126.com";
        document.getElementsByClassName("radio-inline")[4].click();
        document.getElementById("revContactInput_ContactViewModel_AddressLine1").value="guojiaqiao";
        document.getElementById("revContactInput_ContactViewModel_PostalCode").value="401122";
        document.getElementById("revContactInput_ContactViewModel_City").value="chengdu";

        $("-sharprevContactInput_ContactViewModel_CountryCode").click(function(){

            $("-sharprevContactInput_ContactViewModel_CountryCode").val("CN");

            selDom=$("-sharprevContactInput_ContactViewModel_ProvinceState");

            selDom.append("<option value="CQ">Chongqing</option>");//option

            $("-sharprevContactInput_ContactViewModel_CountryCode").change();

        });

        $("-sharprevContactInput_ContactViewModel_CountryCode").click()


        document.getElementById("revContactInput_ContactViewModel_ProvinceState").click()
        var city = document.getElementById("revContactInput_ContactViewModel_ProvinceState");
        for (var i = 0; i < city.length; iPP) {
            if (city[i].text == "Chongqing") { //
                city[i].selected=true; //
        }
    };



    $(".slick-slide").each(function(){
        if ($(this).children("a").html()==""){
            $(this).removeClass("active")
        }
        if ($(this).children("a").html()=="UnionPay"){
            $(this).trigger("focus")
            $(this).children("a").trigger("focus")
            $(this).children("a")[0].click()
            $(this).addClass("active")
        }
    });

        document.getElementsByClassName("push-checkbox")[1].click();
        document.getElementsByClassName("btn-submit")[0].click();

    }
}

let host = document.location.hostname;
if (host.endsWith(".flyscoot.com")) {
    handle(document.location.pathname);
}
May.24,2021

to sum up, there are two problems

  1. how to communicate between python and javascript
    you can use QWebChannel to connect. When you can communicate, your third problem can be solved by dynamically loading scripts.
    refer to python-code-from-javascript-in-pyqt-5-7" rel=" nofollow noreferrer "> https://stackoverflow.com/que.
    and https://doc.qt.io/qt-5/qwebch.
  2. how to use agents
    you can use QtNetwork .
    refer to https://stackoverflow.com/que.

you should make good use of Google search. There are ready answers to these questions.

< hr >

by the way, the entire jquery.js script can be populated in a similar way and does not need to be added to the existing injected.js script file. Learn and use now, be flexible.

Menu