You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 22:10:29