PyQt5 QWebEngineView展示PDF并获取非URL链接内容问题
问题
使用PyQt5.QtWebEngineWidgets展示PDF文件,通过PyMuPDF为PDF中特定文字添加data scheme的链接,但点击这类链接无响应(添加常规URL链接时可正常加载)。相关代码如下:
生成带链接的PDF代码
def create_pdf_with_links(): doc = fitz.open("test.pdf") for count, page in enumerate(doc): text_instances = page.search_for("Kontrollstelle") for instance in text_instances: d = {'kind': 2, 'xref': 0, 'from': instance, 'uri': 'data:Hallo Welt', 'id': ''} page.insert_link(d) doc.save("test.pdf")
展示PDF并处理链接的代码
class MyWebEnginePage(QWebEnginePage): dataLinkClicked = pyqtSignal(str) def acceptNavigationRequest(self, url, _type, isMainFrame): if (_type == QWebEnginePage.NavigationTypeLinkClicked and url.scheme() == 'data'): # send only the url path self.dataLinkClicked.emit(url.path()) return False return super().acceptNavigationRequest(url, _type, isMainFrame) class App(QMainWindow): def __init__(self): super(App, self).__init__() self.pdf_path = os.path.abspath("test.pdf") webView = QWebEngineView() page = MyWebEnginePage(self) # connect to the signal page.dataLinkClicked.connect(self.handleDataLink) webView.setPage(page) # use a data-url webView.settings().setAttribute(QWebEngineSettings.PluginsEnabled, True) webView.settings().setAttribute(QWebEngineSettings.PdfViewerEnabled, True) webView.setUrl(QUrl.fromLocalFile(self.pdf_path)) self.setCentralWidget(webView) def handleDataLink(self, text): print(text) # should print the link: "Hallo Welt" if __name__ == '__main__': app = QApplication(sys.argv) window = App() window.setGeometry(800, 100, 1000, 800) window.show() sys.exit(app.exec_())
需要解决的问题:点击添加的data链接时,如何正确获取其中存储的数据?
解决方案
问题出在两个地方:data链接的格式不符合标准,以及QUrl的内容提取方式错误,修改如下:
1. 修正PyMuPDF中的链接格式
data scheme的标准格式为data:[<mediatype>][;base64],<data>,原代码中的data:Hallo Welt不符合规范,QWebEngine无法识别。需要修改为标准格式,比如使用text/plain作为媒体类型:
d = {'kind': 2, 'xref': 0, 'from': instance, 'uri': 'data:text/plain,Hallo Welt', 'id': ''}
2. 修正QWebEnginePage中链接数据的提取逻辑
QUrl.path()无法正确获取data scheme中的内容,需要从完整的URL字符串中拆分出数据部分:
def acceptNavigationRequest(self, url, _type, isMainFrame): if (_type == QWebEnginePage.NavigationTypeLinkClicked and url.scheme() == 'data'): # 拆分data scheme,提取实际数据 full_data = url.toString() # 以第一个逗号分割,获取逗号后的内容 data_content = full_data.split(',', 1)[1] self.dataLinkClicked.emit(data_content) return False return super().acceptNavigationRequest(url, _type, isMainFrame)
修改后的完整代码
生成带正确链接的PDF代码
def create_pdf_with_links(): doc = fitz.open("test.pdf") for count, page in enumerate(doc): text_instances = page.search_for("Kontrollstelle") for instance in text_instances: # 使用标准data scheme格式 d = {'kind': 2, 'xref': 0, 'from': instance, 'uri': 'data:text/plain,Hallo Welt', 'id': ''} page.insert_link(d) doc.save("test.pdf")
展示PDF并处理链接的代码
from PyQt5.QtWidgets import QMainWindow, QApplication, QWebEngineView from PyQt5.QtWebEngineWidgets import QWebEnginePage, QWebEngineSettings from PyQt5.QtCore import pyqtSignal, QUrl import os import sys class MyWebEnginePage(QWebEnginePage): dataLinkClicked = pyqtSignal(str) def acceptNavigationRequest(self, url, _type, isMainFrame): if (_type == QWebEnginePage.NavigationTypeLinkClicked and url.scheme() == 'data'): full_data = url.toString() # 拆分出data部分 data_content = full_data.split(',', 1)[1] self.dataLinkClicked.emit(data_content) return False return super().acceptNavigationRequest(url, _type, isMainFrame) class App(QMainWindow): def __init__(self): super(App, self).__init__() self.pdf_path = os.path.abspath("test.pdf") webView = QWebEngineView() page = MyWebEnginePage(self) page.dataLinkClicked.connect(self.handleDataLink) webView.setPage(page) webView.settings().setAttribute(QWebEngineSettings.PluginsEnabled, True) webView.settings().setAttribute(QWebEngineSettings.PdfViewerEnabled, True) webView.setUrl(QUrl.fromLocalFile(self.pdf_path)) self.setCentralWidget(webView) def handleDataLink(self, text): print(text) # 现在会正确输出 "Hallo Welt" if __name__ == '__main__': app = QApplication(sys.argv) window = App() window.setGeometry(800, 100, 1000, 800) window.show() sys.exit(app.exec_())
内容的提问来源于stack exchange,提问作者Mazze
相关产品推荐
相关产品推荐

