Skip to content

Instantly share code, notes, and snippets.

@lilydjwg
Created November 24, 2015 08:54
Show Gist options
  • Save lilydjwg/e4ded2f1ca3828ac64d2 to your computer and use it in GitHub Desktop.
Save lilydjwg/e4ded2f1ca3828ac64d2 to your computer and use it in GitHub Desktop.
#!/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