I want to send http GET request using PyQt.
Despite my researches, I haven't found any examples of that simple manipulation in python.
I've ended up with some code (that I have modified according to the hints given by Bakuriu in the comments), but it doesn't work. Let's say I want to make a get request to facebook webpage, and print the answer, which should be the HTML content of the page.
from PyQt4 import QtCore, QtNetwork, QtCore, QtGui
from PyQt4.QtCore import *
import sys
from functools import partial
def printContent():
answerAsText = QString(replyObject.readAll())
print answerAsText
app = QtCore.QCoreApplication(sys.argv)
url = QtCore.QUrl("http://www.facebook.com")
request = QtNetwork.QNetworkRequest()
request.setUrl(url)
manager = QtNetwork.QNetworkAccessManager()
replyObject = manager.get(request)
replyObject.finished.connect(printContent)
sys.exit(app.exec_())
This doesn't raise any error, it just doesn't print anything.
I don't know where the problem is :
Is my request wrong ?
Or is it the way I handle the reply object afterwards ?
Why doesn't it work ? Could somebody please show me a functioning code ?
We need to create a QApplication or QtCoreApplication, because we are using the signal and slot mechanism. Notice also that the response has to be decoded from a QByteArray.
Here is a working example:
#!/usr/bin/python
from PyQt5 import QtCore, QtGui, QtNetwork
import sys
class Example:
def __init__(self):
self.doRequest()
def doRequest(self):
url = "http://webcode.me"
req = QtNetwork.QNetworkRequest(QtCore.QUrl(url))
self.nam = QtNetwork.QNetworkAccessManager()
self.nam.finished.connect(self.handleResponse)
self.nam.get(req)
def handleResponse(self, reply):
er = reply.error()
if er == QtNetwork.QNetworkReply.NoError:
bytes_string = reply.readAll()
print(str(bytes_string, 'utf-8'))
else:
print("Error occured: ", er)
print(reply.errorString())
QtCore.QCoreApplication.quit()
if __name__ == '__main__':
app = QtCore.QCoreApplication([])
ex = Example()
sys.exit(app.exec_())
If you run this application, you will get the HTML code of a very simple web page.
Looks like the URL example is bad. Try www.google.com. I've adapted your code for PyQt5. It works.
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest
import sys
def printContent():
answerAsText = bytes(replyObject.readAll()).decode("utf-8")
print(answerAsText)
class mainClass():
def my_exception_hook(exctype, value, traceback):
print(exctype, value, traceback)
sys._excepthook(exctype, value, traceback)
sys.exit(1)
sys.excepthook = my_exception_hook
if __name__ == '__main__':
app = QApplication(sys.argv)
url = QUrl("http://www.google.com")
request = QNetworkRequest()
request.setUrl(url)
manager = QNetworkAccessManager()
replyObject = manager.get(request)
replyObject.finished.connect(printContent)
sys.exit(app.exec_())
Related
I was learning Qt6, and I wrote a demo putting a local html file into it to test the QWebEngineView Widget. However, the web page shows the info:
Your file counldn't be accessed
It may have been moved, edited, or deleted.
ERR_FILE_NOT_FOUND
Here is my test.py source code:
import sys
from PySide6.QtWidgets import (QApplication, QWidget, QVBoxLayout)
from PySide6 import QtCore
from PySide6.QtWebEngineWidgets import QWebEngineView
class webView(QWidget):
def __init__(self):
super(webView, self).__init__()
self.layout = QVBoxLayout(self)
self.webV = QWebEngineView()
self.fileDir = QtCore.QFileInfo("./docs.html").absoluteFilePath()
print(self.fileDir)
self.webV.load(QtCore.QUrl("file:///" + self.fileDir))
self.layout.addWidget(self.webV)
if __name__ == "__main__":
app = QApplication([])
web = webView()
web.show()
sys.exit(app.exec())
In Addition, the docs.html has been put into the same directory as the test.py file. And when I print the web.fileDir, the result is correct.
You are hardcoded the url and the path may be wrong, in these cases the url is better step by step. I assume that the html is next to the .py then the solution is:
import os
from pathlib import Path
import sys
from PySide6.QtCore import QUrl
from PySide6.QtWidgets import QApplication, QVBoxLayout, QWidget
from PySide6.QtWebEngineWidgets import QWebEngineView
CURRENT_DIRECTORY = Path(__file__).resolve().parent
class webView(QWidget):
def __init__(self):
super(webView, self).__init__()
filename = os.fspath(CURRENT_DIRECTORY / "docs.html")
url = QUrl.fromLocalFile(filename)
self.webV = QWebEngineView()
self.webV.load(url)
layout = QVBoxLayout(self)
layout.addWidget(self.webV)
if __name__ == "__main__":
app = QApplication([])
web = webView()
web.show()
sys.exit(app.exec())
In Qt in general is strongly preferred to use the qrc files, and the Qt resource management system. Here: Can QWebView load images from Qt resource files? is a small yet, neat example of something that is similar to your problem. You may also view the official PySide6 resource usage :
https://doc.qt.io/qtforpython/tutorials/basictutorial/qrcfiles.html
I using pyqt5 for taking the screenshot to the URL. it's the react component. it takes the screenshot only component. don't wait till the API response. wanna take a screenshot after get the API response.
import sys
from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import Qt, QUrl, QTimer
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEngineSettings
class Screenshot(QWebEngineView):
def capture(self, url, output_file):
self.output_file = output_file
self.load(QUrl(url))
self.loadFinished.connect(self.on_loaded)
self.setAttribute(Qt.WA_DontShowOnScreen)
self.show()
def on_loaded(self):
size = self.page().contentsSize().toSize()
self.resize(size)
qt = QTimer()
qt.setInterval(8000)
qt.setSingleShot(True)
qt.singleShot(8000, self.take_screenshot)
def take_screenshot(self):
self.grab().save(self.output_file, b'PNG')
self.app.quit()
app = QApplication([])
s = Screenshot()
s.app = app
s.capture('https://doc.qt.io/qt-5/qtimer.html', 'webpage20.png')
app.exec_()
Note: Under s.capture param URL is just for the example purpose.
I am making a web browser using PyQt5. I am using the following code:
import PyQt5
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtWebKitWidgets import QWebView , QWebPage
from PyQt5.QtWebKit import QWebSettings
from PyQt5.QtNetwork import *
import sys
from optparse import OptionParser
class Browser(QWebView):
def __init__(self):
# QWebView
self.view = QWebView.__init__(self)
#self.view.setPage(MyBrowser())
self.setWindowTitle('Loading...')
self.titleChanged.connect(self.adjustTitle)
#super(Browser).connect(self.ui.webView,QtCore.SIGNAL("titleChanged (const QString&)"), self.adjustTitle)
def load(self,url):
self.setUrl(QUrl(url))
def adjustTitle(self):
self.setWindowTitle(self.title())
app = QApplication(sys.argv)
view = Browser()
view.showMaximized()
view.load("https://duckduckgo.com")
app.exec_()
However, this is what I get:
Can someone please tell me where I am going wrong? Note that it is not a problem of the website. I have tried it with Wikipedia, Stack Overflow and Google. I am using PyQt5 version 5.10.1.
In case you want fullscreen, you have to use:
class Browser(QWebView):
def __init__(self):
# QWebView
self.view = QWebView.__init__(self)
#self.view.setPage(MyBrowser())
self.setWindowTitle('Loading...')
self.titleChanged.connect(self.adjustTitle)
self.showFullScreen()
class Browser(QWebView):
def __init__(self):
super().__init__()
def load(self, url):
self.setUrl(QUrl(url))
def adjustTitle(self):
self.setWindowTitle(self.title())
if __name__ == '__main__':
app = QApplication(sys.argv)
window = Browser()
window.setWindowTitle('Loading...')
window.titleChanged.connect(window.adjustTitle)
window.load("https://duckduckgo.com")
window.showMaximized()
sys.exit(app.exec_())
The program does not know the real sizes of your device so it creates a maximum on its assumed geometry.
You should provide the actual geometry by resize then call showMaximized. So that your geometry will be reachable by the program and a true maximized window will be displayed.
self.resize(998, 878)
self.showMaximized()
I have got an issue when using this following code with a specific url only:
import sys
from PyQt4.QtGui import QApplication
from PyQt4.QtCore import QUrl
from PyQt4.QtWebKit import QWebView,QWebSettings
class Browser(QWebView):
def __init__(self):
QWebView.__init__(self)
Settings = self.settings()
Settings.setAttribute(QWebSettings.JavascriptEnabled, True)
Settings.setAttribute(QWebSettings.JavaEnabled, True)
Settings.setAttribute(QWebSettings.PluginsEnabled, True)
Settings.setAttribute(QWebSettings.AutoLoadImages, True)
self.loadFinished.connect(self._result_available)
def _result_available(self, ok):
frame = self.page().mainFrame()
print unicode(frame.toHtml()).encode('utf-8')
if __name__ == '__main__':
app = QApplication(sys.argv)
view = Browser()
from_url=True
url_to_view='https://www.twitch.tv/'
if from_url==True:
view.load(QUrl(url_to_view))
view.show()
app.exec_()
When running this code I get a blank page and this error:
QNetworkReplyImplPrivate::error: Internal problem, this method must only be called once.
QNetworkReplyImplPrivate::error: Internal problem, this method must only be called once.
It is very strange because I have got this issue only with the https://www.twitch.tv/ url. I had try to replace url with https://www.google.com or anything else and it works fine.
I was expecting that it was relative to python2 and PyQt4, but I have got the same issue when running on python3 and PyQt5 implementation
Someone could help me to properly load the page with pyqt ?
What I am ultimately trying to accomplish is to capture the username and password that the user enters into a website. For example, if the user enters "test#example.com" as the email address into Facebook's login, then clicks submit, I want to store that email address in my PyQt Application.
The closest I've come to achieving this has been using a series of JavaScript commands to place a listener on the "Login Button" that returns the current value of the user parameter. My problem is that the callback that PyQt provides is for when the runJavaScript function is completed, not the javascript event listener. I'm wondering if there is any way to capture the callback function from the JavaScript function, or if there is a better way altogether for me to do this.
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://facebook.com"))
self.loadFinished.connect(self._on_load_finished)
#self.page().runJavaScript("document.getElementById("myBtn").addEventListener("click", displayDate)", print)
def _on_load_finished(self):
print("Finished Loading")
cmds = ["btn=document.getElementById('u_0_r')", # Login Button
"user=document.getElementsByName('email')[0]",
"function get_username(){return user.value}",
"btn.addEventListener('click', get_username)"]
self.page().runJavaScript("; ".join(cmds), lambda x: print("test: %s" % x))
if __name__ == "__main__":
app = QApplication(sys.argv)
web = WebPage()
web.show()
sys.exit(app.exec_()) # only need one app, one running event loop
I found a work around using the "urlChanged" signal that seems to work so far for my applications
import os
import sys
from PyQt5.QtWidgets import QApplication, QVBoxLayout, QWidget
from PyQt5.QtCore import QUrl, QEventLoop
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtWebEngineCore import QWebEngineUrlRequestInterceptor
class WebPage(QWebEngineView):
def __init__(self):
QWebEngineView.__init__(self)
self.current_url = ''
self.load(QUrl("https://facebook.com"))
self.loadFinished.connect(self._on_load_finished)
self.urlChanged.connect(self._on_url_change)
def _on_load_finished(self):
self.current_url = self.url().toString()
def _on_url_change(self):
self.page().runJavaScript("document.getElementsByName('email')[0].value", self.store_value)
def store_value(self, param):
self.value = param
print("Param: " +str(param))
if __name__ == "__main__":
app = QApplication(sys.argv)
web = WebPage()
web.show()
sys.exit(app.exec_()) # only need one app, one running event loop