I'm trying to open a simple html file (something like this)
<html>
<body>
<h1>hello</h1>
</body>
</html>
which does not have any embedded or external JavaScript, inside QtWebEngine using this code
import sys
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWebEngineWidgets import QWebEngineView
class Browser(QWebEngineView):
def __init__(self):
self.view = QWebEngineView.__init__(self)
self.setWindowTitle("Loading ...")
self.titleChanged.connect(self.adjustTitle)
def adjustTitle(self):
self.setWindowTitle(self.title())
if __name__ == "__main__":
app = QApplication(sys.argv)
view = Browser()
view.showMaximized()
url = QUrl.fromLocalFile("simple.html")
view.setUrl(url)
sys.exit(app.exec_())
But when i run it the following error appears in the console
js: Uncaught ReferenceError: jstProcess is not defined
What is jstProcess and how can i define it? (The code works fine if I load some remote resource like bing.com)
Your eg works for me
if give a fully qualified file name for simple as
'/home/me/simple.htm' . Or if simple.htm is in same directory
where I am running the python I do
import sys,os
fname = os.getcwd()+ '/simple.html'
url = QUrl.fromLocalFile(fname)
This is with the pyqt that comes with Debian that I am running
under python 2.
Related
Following this post and the mathjax 3 documentation, I am trying to render a simple html with Mathjax content in PyQt5 using a local copy of the mathjax repo.
The main directory contains the notebook from which the following code is executed, a "mathjax" folder containing the content of the repo (especially the es5 folder). Notice that I tried with 2 paths to the js (comment toward the top) :
import sys
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtCore import QUrl
import os
# <script type="text/javascript" src="file:///Users/mocquin/.../mathjax/es5/tex-chtml-full.js">
pageSource = """
<html><head>
<script type="text/javascript" src="./mathjax/es5/tex-chtml-full.js">
</script></head>
<body>
<p><mathjax style="font-size:2.3em">$$u = \int_{-\infty}^{\infty}(awesome)\cdot du$$</mathjax></p>
</body></html>
"""
app = QApplication(sys.argv)
webView = QWebEngineView()
webView.setHtml(pageSource, baseUrl=QUrl(os.path.abspath('')))
webView.show()
sys.exit(app.exec_())
But this only renders the content without the "latex parsing"
What am I missing so that the mathjax is indeed linked to the html ?
The problem with your example is that you aren't using the correct format for the src path and base url. The src path must be a plain relative path, and the base url should be a backslash-terminated absolute path to the directory containing the mathjax directory.
Assuming the mathjax directory is in the same directory as the python script, the following should work correctly (at least, it does for me):
import sys, os
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWebEngineWidgets import QWebEngineView
pageSource = """
<html><head>
<script type="text/javascript" async src="mathjax/es5/tex-chtml-full.js"></script>
</head><body>
<p><mathjax style="font-size:2.3em">$$u = \int_{-\infty}^{\infty}(awesome)\cdot du$$</mathjax></p>
</body></html>
"""
baseurl = QUrl.fromLocalFile(os.path.dirname(os.path.abspath(__file__)) + '/')
print(f'BASEURL: {baseurl.toString()!r}') # BASEURL: 'file:///home/tmp/test/'
app = QApplication(sys.argv)
webView = QWebEngineView()
webView.setHtml(pageSource, baseUrl=baseurl)
webView.show()
sys.exit(app.exec_())
I wrote a python test program like this to show openstreetmap:
from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import QUrl
from PyQt5.QtWebEngineWidgets import QWebEngineView
import sys
def mainPyQt5():
url = 'file:///./index.html'
app = QApplication(sys.argv)
browser = QWebEngineView()
browser.load(QUrl(url))
browser.show()
sys.exit(app.exec_())
mainPyQt5()
index.html fetched by QWebEngineView simply calls openstreetmap:
<title>OSM and Leaflet</title>
<link rel = "stylesheet" href = "http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css"/>
<div id = "map" style = "width: 900px; height: 580px"></div><script src = "http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<script>
// Creating map options
var mapOptions = {
center: [45.641174, 9.114828],
zoom: 10
}
// Creating a map object
var map = new L.map('map', mapOptions);
// Creating a Layer object
var layer = new L.TileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png');
// Adding layer to the map
map.addLayer(layer);
</script>
If I fetch index.html with a ordinary browser the map is shown as expected but if I call the simple python program using QWebEngineView no tiles are downloaded from openstreetmap. If I replace openstreetmap with maps.stamen.com everything is fine both with a browser or the python script.
By default QtWebEngine does not set default headers like popular browsers do. In this case the openstreetmap server needs to know the "Accept-Language" to produce the maps since for example the names of the cities will depend on the language to filter non-browser traffic. The solution is to implement a QWebEngineUrlRequestInterceptor that adds that header:
import os.path
import sys
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWebEngineCore import QWebEngineUrlRequestInterceptor
from PyQt5.QtWebEngineWidgets import QWebEngineView
class Interceptor(QWebEngineUrlRequestInterceptor):
def interceptRequest(self, info):
info.setHttpHeader(b"Accept-Language", b"en-US,en;q=0.9,es;q=0.8,de;q=0.7")
def mainPyQt5():
CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
filename = os.path.join(CURRENT_DIR, "index.html")
app = QApplication(sys.argv)
browser = QWebEngineView()
interceptor = Interceptor()
browser.page().profile().setUrlRequestInterceptor(interceptor)
browser.load(QUrl.fromLocalFile(filename))
browser.show()
sys.exit(app.exec_())
if __name__ == "__main__":
mainPyQt5()
I'm building a browser using PyQt5. It's a rather huge code, but this is the main problem I'm facing. The code is this:
import sys
from PyQt5.QtCore import QUrl
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtWidgets import QApplication, QMainWindow
app = QApplication(sys.argv)
web = QWebEngineView()
file = open("example.html", "r")
html = file.read()
web.setHtml(html)
file.close()
web.show()
sys.exit(app.exec_())
The problem is that the rendering is rather strange.Image of the rendering is here.
The contents of the example.html file:
<!DOCTYPE html>
<head><title>JS Example</title></head>
<h1>JS example</h1>
<p><button type = 'button' onclick = "document.getElementById('tobeshown').style.display='block'">Show hidden parts of this page</button></p>
<p id = 'tobeshown' style = "display:none">
Peekaboo!
</p>
<p>
<button type = 'button' onclick="document.getElementById('tobeshown').style.display='none'">Hide it!</button>
</p>
</body>
</html>
The expected output(this is in Mozilla Firefox browser): here
Can anyone tell me why the PyQt5 rendering engine produces those symbols at the top? And what can I do to resolve it? Thank you very much.
So the problem is not WebEngine's rendering but instead Python's reading of a file. Changing the file's encoding to UTF-8 solved the problem for me.
Here's my problem: I want to load a local html file into a QWebView in Python.
EDIT: I use PySide as a Qt package.
My code:
class myWindow(QWidget):
def __init__(self, parent=None):
self.view = QWebView(self)
filepath = "file://" + os.path.join(os.path.dirname(__file__), 'googlemap.html')
self.view.load(QUrl(filepath))
This is just showing me a blank widget.
If I change
self.view.load(QUrl(filepath)
by
self.view.load(QUrl("http://www.google.com/"))
It works fine.
However, the file is clearly in the good directory and I can open the same file directly with my browser.
EDIT 2:
The problem appears after an update on my Raspberry Pi 2 (which runs the code above)
Two observations:
path needs to be absolute (not relative)
use QUrl.fromLocalFile(path)
so something like this
file_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "aa.html"))
local_url = QUrl.fromLocalFile(file_path)
browser.load(local_url)
should work.
Full example:
from PyQt4.QtWebKit import QWebView
from PyQt4.QtGui import QApplication
from PyQt4.QtCore import QUrl
import sys
import os
app = QApplication(sys.argv)
browser = QWebView()
file_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "aa.html"))
local_url = QUrl.fromLocalFile(file_path)
browser.load(local_url)
browser.show()
app.exec_()
I would like to use PyQt/QWebview to 1) load a specific url, 2) enter information into a form, 3) click buttons/links. Mechanize does not work because I need an actual browser.
Here's my code:
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtWebKit import *
from PyQt4 import QtCore
app = QApplication(sys.argv)
web = QWebView()
web.load(QUrl("https://www.lendingclub.com/account/gotoLogin.action"))
def fillForm():
doc = web.page().mainFrame().documentElement()
user = doc.findFirst("input[id=master_username]")
passwd = doc.findFirst("input[id=master_password]")
user.setAttribute("value", "email#email.com")
passwd.setAttribute("value", "password")
button = doc.findFirst("input[id=master_sign-in-submit]")
button.evaluateJavaScript("click()")
QtCore.QObject.connect(web, QtCore.SIGNAL("loadFinished"), fillForm)
web.show()
sys.exit(app.exec_())
The page loads correctly, but no input is entered and the form is not submitted. Any ideas?
This helped me to make it work:
user.setAttribute("value", "email#email.com")
-->
user.evaluateJavaScript("this.value = 'email#email.com'")
Attribute and property are different things.
One more fix:
click() --> this.click()
For anyone looking to do this with PyQt5, this example may help as several things have changed. Obviously the javascript needs to be adjusted based on the contents of the website.
import os
import sys
from PyQt5.QtWidgets import QApplication, QVBoxLayout, QWidget
from PyQt5.QtCore import QUrl, QEventLoop
from PyQt5.QtWebEngineWidgets import QWebEngineView
class WebPage(QWebEngineView):
def __init__(self):
QWebEngineView.__init__(self)
self.load(QUrl("https://www.url.com"))
self.loadFinished.connect(self._on_load_finished)
def _on_load_finished(self):
print("Finished Loading")
self.page().toHtml(self.Callable)
def Callable(self, html_str):
self.html = html_str
self.page().runJavaScript("document.getElementsByName('loginid')[0].value = 'email#email.com'")
self.page().runJavaScript("document.getElementsByName('password')[0].value = 'test'")
self.page().runJavaScript ("document.getElementById('signin').click()")
if __name__ == "__main__":
app = QApplication(sys.argv)
web = WebPage()
web.show()
sys.exit(app.exec_()) # only need one app, one running event loop
You might be able to do it with Webkit/QWebView but what about using selenium: http://code.google.com/p/selenium/ ? It is designed for exactly this kind of browser automation and has nice python bindings.