经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » HTML/CSS » 浏览器 » 查看文章
PyQt5内嵌浏览器注入JavaScript脚本实现自动化操作的代码实例
来源:jb51  时间:2019/2/14 9:08:12  对本文有异议

概要

应同学邀请,演示如何使用 PyQt5 内嵌浏览器浏览网页,并注入 Javascript 脚本实现自动化操作。

下面测试的是一个廉价机票预订网站(http://www.flyscoot.com/),关键点如下

  1. 使用 QWebEngineView 加载网页,并显示进度。
  2. 在默认配置(QWebEngineProfile)中植入 Javascript 内容,这样脚本会在所有打开的网页中执行,不论跳转到哪个网址。
  3. Javascript 脚本使用网址中的路径名,判断当前网页位置,从而决定执行哪种操作。

python 代码示例

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. '''使用 PyQt5 内嵌浏览器浏览网页,并注入 Javascript 脚本实现自动化操作。'''
  4. import os
  5. import sys
  6. from datetime import datetime
  7. from PyQt5.QtWidgets import (
  8. QWidget, QApplication, QVBoxLayout, QHBoxLayout,
  9. QDesktopWidget, QTextEdit, QLabel, QLineEdit, QPushButton,
  10. QFileDialog, QProgressBar,
  11. )
  12. from PyQt5.QtCore import QUrl, pyqtSlot
  13. from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEngineProfile, QWebEngineScript, QWebEnginePage
  14. class Browser(QWidget):
  15. def __init__(self):
  16. super().__init__()
  17. self.init_ui()
  18. # 脚本
  19. self.profile = QWebEngineProfile.defaultProfile()
  20. self.script = QWebEngineScript()
  21. self.prepare_script()
  22. def init_ui(self):
  23. self.webView = QWebEngineView()
  24. self.logEdit = QTextEdit()
  25. self.logEdit.setFixedHeight(100)
  26. self.addrEdit = QLineEdit()
  27. self.addrEdit.returnPressed.connect(self.load_url)
  28. self.webView.urlChanged.connect(
  29. lambda i: self.addrEdit.setText(i.toDisplayString()))
  30. self.jsEdit = QLineEdit()
  31. self.jsEdit.setText('inject.js')
  32. loadUrlBtn = QPushButton('加载')
  33. loadUrlBtn.clicked.connect(self.load_url)
  34. chooseJsBtn = QPushButton('选择脚本文件')
  35. chooseJsBtn.clicked.connect(self.choose_js_file)
  36. # 导航/工具
  37. top = QWidget()
  38. top.setFixedHeight(80)
  39. topBox = QVBoxLayout(top)
  40. topBox.setSpacing(0)
  41. topBox.setContentsMargins(5, 0, 0, 5)
  42. progBar = QProgressBar()
  43. progBox = QHBoxLayout()
  44. progBox.addWidget(progBar)
  45. topBox.addLayout(progBox)
  46. naviBox = QHBoxLayout()
  47. naviBox.addWidget(QLabel('网址'))
  48. naviBox.addWidget(self.addrEdit)
  49. naviBox.addWidget(loadUrlBtn)
  50. topBox.addLayout(naviBox)
  51. naviBox = QHBoxLayout()
  52. naviBox.addWidget(QLabel('注入脚本文件'))
  53. naviBox.addWidget(self.jsEdit)
  54. naviBox.addWidget(chooseJsBtn)
  55. topBox.addLayout(naviBox)
  56. self.webView.loadProgress.connect(progBar.setValue)
  57. # 主界面
  58. layout = QVBoxLayout(self)
  59. layout.addWidget(self.webView)
  60. layout.addWidget(top)
  61. layout.addWidget(self.logEdit)
  62. self.show()
  63. self.resize(1024, 900)
  64. self.center()
  65. def center(self):
  66. qr = self.frameGeometry()
  67. cp = QDesktopWidget().availableGeometry().center()
  68. qr.moveCenter(cp)
  69. self.move(qr.topLeft())
  70. @pyqtSlot()
  71. def load_url(self):
  72. url = self.addrEdit.text().strip()
  73. if not url.lower().startswith('http://') and not url.lower().startswith('https://'):
  74. url = 'http://{}'.format(url)
  75. self.load(url)
  76. @pyqtSlot()
  77. def choose_js_file(self):
  78. f, _ = QFileDialog.getOpenFileName(filter="Javascript files(*.js)")
  79. if os.path.isfile(f):
  80. self.jsEdit.setText(f)
  81. self.prepare_script()
  82. def prepare_script(self):
  83. path = self.jsEdit.text().strip()
  84. if not os.path.isfile(path):
  85. self.log('invalid js path')
  86. return
  87. self.profile.scripts().remove(self.script)
  88. with open(path, 'r') as f:
  89. self.script.setSourceCode(f.read())
  90. self.profile.scripts().insert(self.script)
  91. self.log('injected js ready')
  92. def log(self, msg, *args, **kwargs):
  93. m = msg.format(*args, **kwargs)
  94. self.logEdit.append('{} {}'.format(
  95. datetime.now().strftime('%H:%M:%S'), m))
  96. def load(self, url):
  97. self.log(f'loading {url}')
  98. self.addrEdit.setText(url)
  99. self.webView.load(QUrl(url))
  100. if __name__ == '__main__':
  101. app = QApplication(sys.argv)
  102. b = Browser()
  103. b.load('http://www.flyscoot.com/')
  104. sys.exit(app.exec_())

Javascript 脚本示例

  1. // 简单起见,这里只演示部分页面,脚本内容摘自 Heng丶原贴文。
  2. function handle(path) {
  3. // 首页
  4. if (path == '/zh') {
  5. document.getElementsByClassName('radio-inline')[1].click();
  6. document.getElementById('oneway_from').value='广州 (CAN)';
  7. document.getElementById('oneway_to').value='新加坡 (SIN)';
  8. document.getElementById('oneway_departuredate').value='2018年9月10日';
  9. document.getElementsByClassName('btn--booking')[1].click();
  10. return;
  11. }
  12. // 选择航班
  13. if (path == '/Book/Flight') {
  14. document.getElementsByClassName('price--sale')[0].click();
  15. document.getElementsByClassName('heading-4')[0].click();
  16. document.getElementsByClassName('btn-submit')[0].click();
  17. return;
  18. }
  19. // 乘客信息
  20. if (path == '/BookFlight/Passengers') {
  21. document.getElementsByClassName('fname1')[0].value = "匿名";
  22. }
  23. }
  24. let host = document.location.hostname;
  25. if (host.endsWith('.flyscoot.com')) {
  26. handle(document.location.pathname);
  27. }

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对w3xue的支持。如果你想了解更多相关内容请查看下面相关链接

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号