[QtWebKit.QWebView] Systemsprache unterdrücken

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
lackschuh
User
Beiträge: 281
Registriert: Dienstag 8. Mai 2012, 13:40

Hallo

Ich bastel mir gerade eine "Browser". Soweit funktioniert auch alles was ich haben will nur eben die "Unterdrückung" der Systemsprache nicht bzw da tritt ein mir unbekanntes Phänomen auf. Denn hin und wieder wird auf einer der unten stehenden Seiten die Systemsprache nicht angezeigt. D.h. wenn ich eine Seite mehrmals aktualisiere, dann verschwindet die Systemsprache.

Folgendes steht im Programm:

Code: Alles auswählen

        self.request = QtNetwork.QNetworkRequest()
        self.request.setRawHeader("Accept-Language", QtCore.QByteArray ("en"))
Eine Abfrage auf www.whoer.net oder http://show-ip.net/useragent/ zeigt mir neben 'en' auch mehrmals de,de-de an. JS habe ich deaktiviert und nutzen tue ich Win 7x64.

Kann mir jemand plausibel erklären, was da vonstatten geht?

mfg
BlackJack

@lackschuh: Das ist ja irgendwie kein funktionierendes Minimalbeispiel. Das im Betreff erwähnte `QWebView` kommt zum Beispiel überhaupt nicht vor.

Hast Du das Problem bei diesem Beispiel hier auch?

Code: Alles auswählen

#!/usr/bin/env python
# coding: utf8
import sys
from PyQt4.QtCore import QCoreApplication, QUrl
from PyQt4.QtNetwork import QNetworkAccessManager, QNetworkRequest


def main():
    application = QCoreApplication(sys.argv)

    def process_reply(reply):
        print reply.readAll()
        application.quit()

    manager = QNetworkAccessManager(application)
    manager.finished.connect(process_reply)

    request = QNetworkRequest()
    request.setRawHeader('Accept-Language', 'en')
    request.setUrl(QUrl('http://show-ip.net/useragent/'))

    manager.get(request)

    sys.exit(application.exec_())
    

if __name__ == '__main__':
    main()
lackschuh
User
Beiträge: 281
Registriert: Dienstag 8. Mai 2012, 13:40

Hi

Nein, es wird nur "en" angezeigt.

Code: Alles auswählen

<font color="#008000">Accept-Language:</font> en <br />
Anbei mal der ganze Code:

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys
import re
from PyQt4 import QtCore, QtGui, QtNetwork, QtWebKit
from PyQt4.QtWebKit import QWebSettings
from ui_test import Ui_MainWindow

# ----- Broweser Einstallung -----
einstellungen = {
    QWebSettings.JavaEnabled : False,
    QWebSettings.JavascriptEnabled : False,
    QWebSettings.PluginsEnabled : False,
    QWebSettings.JavascriptCanOpenWindows : False,
    }

for key, value in einstellungen.iteritems():
    QWebSettings.globalSettings().setAttribute(key, value)

# ----- Socks5 Einstellungen -----
proxy = QtNetwork.QNetworkProxy(QtNetwork.QNetworkProxy.Socks5Proxy, "127.0.0.1", 8010)
QtNetwork.QNetworkProxy.setApplicationProxy(proxy)

# ----- Start Hauptprogramm -----
def main(argv):
    app = QtGui.QApplication(argv)
    MainWindow = BrowserWindow()
    MainWindow.show()
    sys.exit(app.exec_())

# ---- Definition user-agent -----
class WebPage(QtWebKit.QWebPage):
    def userAgentForUrl(self, url):
        return "Mozilla/6.0 (X11; Linux x86_64; rv:7.0.1) Gecko/20100101 Firefox/7.0.1"

class BrowserWindow(QtGui.QMainWindow,QtWebKit.QWebPage):
    def __init__(self, *args):
        QtGui.QMainWindow.__init__(self, *args)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        #start ProgressBar
        self.ui.webView.loadProgress.connect(self.print_percent)
        self.create_connects()

    def create_connects(self):
        self.ui.editAddress.returnPressed.connect(self.load_page)
        self.ui.webView.urlChanged.connect(self.update_url)
        self.connect(self.ui.actionExit, QtCore.SIGNAL('triggered()'), QtGui.qApp, QtCore.SLOT('quit()'))
        self.connect(self.ui.actionStop, QtCore.SIGNAL('triggered()'), (self.ui.webView.stop))
        self.connect(self.ui.actionBack, QtCore.SIGNAL('triggered()'), (self.ui.webView.back))
        self.connect(self.ui.actionForward, QtCore.SIGNAL('triggered()'), (self.ui.webView.forward))
        self.connect(self.ui.actionReload, QtCore.SIGNAL('triggered()'), (self.ui.webView.reload))

    def print_percent(self, percent):
            self.ui.progressBar.setValue(percent)

    @QtCore.pyqtSlot(QtCore.QUrl)
    def update_url(self, url):
        self.ui.editAddress.setText(url.toString())

    @QtCore.pyqtSlot()
    def load_page(self):
        #set user-agent and language
        self.request = QtNetwork.QNetworkRequest()
        self.request.setRawHeader("Accept-Language", QtCore.QByteArray ("en"))
        self.ui.webView.setPage(WebPage())
        stringUrl = unicode(self.ui.editAddress.text())
        if not re.search(r"^http", stringUrl):
            stringUrl = "http://" +stringUrl
        url = QtCore.QUrl(stringUrl)
        self.request.setUrl(url)
        self.ui.webView.load(self.request)
        self.ui.editAddress.clearFocus()

    def closeEvent(self, event):
        reply = QtGui.QMessageBox.question(self, 'Message',
            "Sind Sie sicher, dass Sie das Programm beenden wollen?", QtGui.QMessageBox.Yes | 
            QtGui.QMessageBox.No)
        if reply == QtGui.QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()

if __name__ == "__main__":
    main(sys.argv)

EDIT:

Folgendes ist mir gerade aufgefallen. Wenn ich die Seite http://show-ip.net/useragent/ direkt aufrufe, dann wird die Sprache als 'en' angezeigt. Wenn ich aber über google.com die Seite aufrufe, dann wird neben 'en' auch 'de' bzw die Systemsprache angezeigt. Wenn ich die Systemsprache auf de-CH, de-LI oder de-BE ändere, dann wird eben diese angezeigt.

Aufruf über google:
User-Agent: Mozilla/6.0 (X11; Linux x86_64; rv:7.0.1) Gecko/20100101 Firefox/7.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Referer: http://www.google.de/search?output=sear ... nmOdWEgagG
Connection: Keep-Alive
Accept-Encoding: gzip
Accept-Language: de-CH,en,*
direkter Aufruf:
Accept-Language: en
User-Agent: Mozilla/6.0 (X11; Linux x86_64; rv:7.0.1) Gecko/20100101 Firefox/7.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Connection: Keep-Alive
Accept-Encoding: gzip
Host: show-ip.net
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@lackschuh: Ich versteh Dich nicht. Was erwartest Du wenn Du explizit "Accept-Language: en" angibst was die Seite melden soll?
BlackJack

@Sirius3: Es soll *nicht* 'de' angezeigt werden wenn er nur 'en' angibt. (Wird es ja auch nicht, aber das sieht lackschuh anscheinend nicht.)

@lackschuh:Wenn Du in irgendeiner angezeigten Seite auf einen Link klickst, dann wird *nicht* Deine `load_page()`-Methode aufgerufen, also wird auch *nicht* 'en' als ausschliesslich akzeptierte Sprache gesetzt. In sofern sollte das Ergebnis jetzt nicht wirklich verwundern.

Edit: Ich finde es übrigens auch komisch, dass die Klasse gleichzeitig von `QMainwindow` und `QWebPage` erbt. Das beisst sich IMHO irgendwie. Es erbt aber nicht von `Ui_MainWindow`, da wird ein Exemplar von als Attribut `ui` gesetzt, beim `setupUi()` auf *dem* Objekt wird aber `self` übergeben. An der Stelle wird es IMHO komplett wirr.

Bei den Signalen und Slots verwendest Du veraltetes und viel zu umständliches. Die Signale existieren als Attribute auf des Widgets und haben eine `connect()`-Methode. Das ist viel kürzer, man braucht kein `QtCore.SIGNAL()` und `QtCore.SLOT()` mehr, und typsicherer ist es auch. Auf der Slot-Seite braucht man auch kein `QtCore.pyqtSlot()` als Decorator. Das braucht man eigentlich nur noch wenn man Signaturen überladen will oder muss. Ansonsten kann jedes aufrufbare Python-Objekt direkt als Slot verwendet werden.
lackschuh
User
Beiträge: 281
Registriert: Dienstag 8. Mai 2012, 13:40

BlackJack hat geschrieben:@lackschuh:Wenn Du in irgendeiner angezeigten Seite auf einen Link klickst, dann wird *nicht* Deine `load_page()`-Methode aufgerufen, also wird auch *nicht* 'en' als ausschliesslich akzeptierte Sprache gesetzt. In sofern sollte das Ergebnis jetzt nicht wirklich verwundern.
Klingt logisch :wink:
Was wäre dann in PyQt eine theoretische Möglichkeit, die Sprache auch bei Klicks auf einen Link in 'en' anzuzeigen. Den setRawHeader("Accept-Language", QtCore.QByteArray ("en")) eine ebene höher einbauen?

mfg
BlackJack

@lackschuh: Ist jetzt nur geraten, aber vielleicht kann man das `downloadRequested`-Signat von `QWebPage` verwenden um den `request` der da übergeben wird zu verändern.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Mal eine Anmerkung zu `if not re.search(r"^http", stringUrl)`: Reguläre Ausdücke sind ja desöfteren ganz praktisch, aber hier würde ich dann doch eher das Python-eigene `.startswith()` auf der Zeichenkette benutzen. Eine RegExp kann man IMHO dann verwenden, wenn man andernfalls eine Art Zustandsautomaten bauen müsste, der das gewünschte Muster ermittelt. Das ist hier aber ganz sicher nicht der Fall.

Im Übrigen hat `QUrl` seit Qt 4.6 eine praktische Möglichkeit, um von Benutzerseite eingegebene Strings möglichst in eine gültige und erwartungskonforme Form zu bringen. Ungetestet:

Code: Alles auswählen

url = QtCore.QUrl.fromUserInput(self.ui.editAddress.text())
if not url.isValid():
    raise ValueError('Unable to recognize given URL')
    # bzw Fenster (z.B. QMessageBox) mit Fehlermeldung
self.request.setUrl(url)
# und so weiter...
Wobei `.isValid()` natürlich optional ist und nichts darüber aussagt, ob die URL auch tatsächlich aufrufbar ist.
lunar

BlackJack hat geschrieben:Es erbt aber nicht von `Ui_MainWindow`, da wird ein Exemplar von als Attribut `ui` gesetzt, beim `setupUi()` auf *dem* Objekt wird aber `self` übergeben. An der Stelle wird es IMHO komplett wirr.
Uhm, dieser Weg, das Designer-Modul zu verwenden, ist nicht wirr, sondern dokumentiert. Und imho auch zu bevorzugen, weil Vererbung vermieden wird, und Attribute des generierten Quelltexts einen eigenen Namensraum erhalten. Zudem muss man dann nur eine einzige Zeile ändern, wenn man die UI-Datei dynamisch laden möchte, anstatt jeden Zugriff auf Attribute der UI anpassen zu müssen.
BlackJack

@lunar: Ah, okay, ich dachte `setupUI()` würde die Attribute auf dem übergebenen Objekt setzen, wie das dynamische Laden das macht wenn man da ein Objekt übergibt.
Antworten