Created
November 24, 2015 08:54
-
-
Save lilydjwg/e4ded2f1ca3828ac64d2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import os | |
import sys | |
from urllib.parse import parse_qs | |
import subprocess | |
import json | |
from PyQt5 import QtWebKit, QtWebKitWidgets | |
from PyQt5.QtCore import ( | |
QUrl, QSize, QTranslator, QLocale, QLibraryInfo, | |
QStandardPaths, QSettings, | |
) | |
from PyQt5 import QtNetwork | |
from PyQt5.QtWidgets import ( | |
QApplication, QStatusBar, QLabel, QWidget, QVBoxLayout, | |
) | |
# TODO: window.open | |
# TODO: 桌面通知(https://github.com/QupZilla/qtwebkit-plugins) | |
# TODO: 不支持声音(https://bugreports.qt.io/browse/QTBUG-29612) | |
class MyWebPage(QtWebKitWidgets.QWebPage): | |
def __init__(self, ua): | |
self._ua = ua | |
super().__init__() | |
def userAgentForUrl(self, url): | |
return self._ua or super().userAgentForUrl(url) | |
class Browser(QWidget): | |
def __init__(self, url, title, settings, ua=None): | |
super().__init__() | |
self.url = url | |
self.title = title | |
self.ua = ua | |
self.settings = settings | |
self.load_cookies() | |
self.initUI() | |
def closeEvent(self, evt): | |
self.save_cookies() | |
super().closeEvent(evt) | |
def load_cookies(self): | |
print('loading cookies') | |
self.cj = QtNetwork.QNetworkCookieJar() | |
self.cj.setAllCookies([ | |
QtNetwork.QNetworkCookie.parseCookies(c.encode('utf-8'))[0] | |
for c in self.get("cookiejar", []) | |
]) | |
def save_cookies(self): | |
print('saving cookies') | |
self.put("cookiejar", [ | |
str(c.toRawForm(), 'utf-8') for c in self.cj.allCookies() | |
]) | |
def put(self, key, value): | |
"Persist an object somewhere under a given key" | |
self.settings.setValue(key, json.dumps(value)) | |
self.settings.sync() | |
def get(self, key, default=None): | |
"""Get the object stored under 'key' in persistent storage, | |
or the default value""" | |
v = self.settings.value(key) | |
if v is None: | |
return default | |
return json.loads(v) | |
def initUI(self): | |
statusbar = QStatusBar(self) | |
view = QtWebKitWidgets.QWebView(self) | |
view.setPage(MyWebPage(self.ua)) | |
error_shown = False | |
my_showing = False | |
url = self.url | |
def on_loading(): | |
# print('loading') | |
nonlocal error_shown | |
if my_showing: | |
return | |
if error_shown: | |
error_shown = False | |
statusbar.showMessage('正在载入……') | |
def on_loaded(status): | |
# print('loaded', status) | |
nonlocal error_shown, my_showing | |
if my_showing: | |
error_shown = True | |
my_showing = False | |
if error_shown: | |
return | |
if not status: | |
show_error() | |
return | |
statusbar.showMessage('就绪') | |
def on_progress(percent): | |
# print('progress', percent) | |
if my_showing or error_shown: return | |
statusbar.showMessage('正在载入 (%d%%)……' % percent) | |
def on_title_changed(new): | |
if new: | |
self.setWindowTitle('%s - %s' % (new, self.title)) | |
else: | |
self.setWindowTitle(self.title) | |
def on_icon_changed(): | |
self.setWindowIcon(view.icon()) | |
def show_error(): | |
nonlocal my_showing | |
if error_shown: return | |
statusbar.showMessage('出错') | |
my_showing = True | |
print(view.url().toString(), url) | |
view.setHtml( | |
'<title>出错了!</title>' | |
'<h1>出错了!</h1><p>载入页面时发生错误,请检查您的网络连接,或者稍后' | |
'<a href="%s">重新载入</a>。' % url | |
) | |
def on_link_clicked(u): | |
print('link-clicked', u) | |
url = None | |
if u.host() == 'wx.qq.com': | |
q = parse_qs(u.query()) | |
if q.get('requrl'): | |
url = q.get('requrl', [None])[0] | |
if url is None: | |
url = u.url() | |
subprocess.check_call(['xdg-open', url]) | |
view.loadStarted.connect(on_loading) | |
view.loadProgress[int].connect(on_progress) | |
view.loadFinished[bool].connect(on_loaded) | |
view.titleChanged[str].connect(on_title_changed) | |
view.settings().enablePersistentStorage() | |
view.iconChanged.connect(on_icon_changed) | |
view.page().setLinkDelegationPolicy(QtWebKitWidgets.QWebPage.DelegateAllLinks) | |
view.linkClicked[QUrl].connect(on_link_clicked) | |
manager = view.page().networkAccessManager() | |
cache = QtNetwork.QNetworkDiskCache(self) | |
cachedir = QStandardPaths.standardLocations(QStandardPaths.CacheLocation)[0] | |
cache.setCacheDirectory(cachedir) | |
manager.setCache(cache) | |
print('cache dir:', cachedir) | |
manager.setCookieJar(self.cj) | |
view.load(QUrl(url)) | |
vbox = QVBoxLayout() | |
vbox.addWidget(view, stretch=1) | |
vbox.addWidget(statusbar) | |
vbox.setContentsMargins(0, 0, 0, 0) | |
self.setLayout(vbox) | |
self.setMinimumSize(QSize(800, 600)) | |
self.setWindowTitle(self.title) | |
self.showMaximized() | |
def main(): | |
app = QApplication(sys.argv) | |
qt_translator = QTranslator() | |
qt_translator.load("qt_" + QLocale.system().name(), | |
QLibraryInfo.location(QLibraryInfo.TranslationsPath)) | |
app.installTranslator(qt_translator) | |
QtWebKit.QWebSettings.globalSettings().setAttribute( | |
QtWebKit.QWebSettings.PluginsEnabled, True) | |
b = Browser( | |
'https://wx.qq.com/', '微信独立版', | |
QSettings('qtweixin'), | |
) | |
app.exec() | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment