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

PyQt5嵌入MarineTraffic JS地图报连接失败错误如何排查解决

问题定位

连接失败由三个核心原因共同导致:

  • 加载协议不兼容:使用file://协议加载本地index.html时,MarineTraffic服务端会识别到非HTTP/HTTPS来源,直接触发反爬拦截,拒绝返回地图资源。
  • 权限配置缺失:QtWebEngine默认关闭本地内容访问远程资源、本地存储等权限,会拦截地图JS脚本、瓦片资源的加载请求;同时默认UA携带QtWebEngine标识,会被服务端判定为非常规客户端直接拦截。
  • 通信逻辑不完整:代码中注册了QWebChannel对象,但前端HTML未引入Qt官方的qwebchannel.js适配脚本,前后端通信链路本身无法打通。
修正后的实现代码
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets, QtWebChannel
from PyQt5.QtWebEngineWidgets import QWebEngineSettings

class Backend(QtCore.QObject):
    valueChanged = QtCore.pyqtSignal(str)

    def __init__(self, parent=None):
        super().__init__(parent)
        self._value = ""

    @QtCore.pyqtProperty(str)
    def value(self):
        return self._value

    @value.setter
    def value(self, v):
        self._value = v
        self.valueChanged.emit(v)


class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.webEngineView = QtWebEngineWidgets.QWebEngineView()
        self.label = QtWidgets.QLabel(alignment=QtCore.Qt.AlignCenter)

        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(self.webEngineView, stretch=1)
        lay.addWidget(self.label)

        # 开启WebEngine必要运行权限
        settings = self.webEngineView.settings()
        settings.setAttribute(QWebEngineSettings.JavascriptEnabled, True)
        settings.setAttribute(QWebEngineSettings.LocalContentCanAccessRemoteUrls, True)
        settings.setAttribute(QWebEngineSettings.LocalStorageEnabled, True)

        backend = Backend(self)
        backend.valueChanged.connect(self.label.setText)
        backend.valueChanged.connect(self.foo_function)
        self.channel = QtWebChannel.QWebChannel()
        self.channel.registerObject("backend", backend)
        self.webEngineView.page().setWebChannel(self.channel)

        # 嵌入页面模板,替换为你自己的MarineTraffic接入代码
        embed_html = """
        <!DOCTYPE html>
        <html>
        <head>
            <meta charset="utf-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <!-- 引入Qt WebChannel适配脚本 -->
            <script src="qrc:///qtwebchannel/qwebchannel.js"></script>
            <style>*{margin:0;padding:0;height:100%;width:100%;}</style>
        </head>
        <body>
            <div id="mapContainer" style="width:100%;height:100%"></div>
            <script>
                // 初始化前后端通信
                new QWebChannel(qt.webChannelTransport, function(channel) {
                    window.backend = channel.objects.backend;
                    backend.value = "地图容器初始化完成";
                });
                // 从这里开始粘贴MarineTraffic官方提供的地图嵌入JS代码
                // 注意将地图挂载到上面的mapContainer节点
            </script>
        </body>
        </html>
        """
        # 加载HTML时指定MarineTraffic为基地址,解决跨域和来源校验问题
        self.webEngineView.setHtml(
            embed_html, 
            baseUrl=QtCore.QUrl("https://www.marinetraffic.com/")
        )

    @QtCore.pyqtSlot(str)
    def foo_function(self, value):
        print("收到前端消息:", value)


if __name__ == "__main__":
    import sys
    # 高DPI适配
    QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
    # 修改全局UA为普通Chrome标识,绕过客户端校验
    profile = QtWebEngineWidgets.QWebEngineProfile.defaultProfile()
    profile.setHttpUserAgent(
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
    )

    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.resize(1280, 800)
    w.show()
    sys.exit(app.exec_())
注意事项
  • 必须从MarineTraffic嵌入地图页面获取你自己的专属接入代码(包含接入密钥、自定义区域、图层配置),粘贴到代码中标注的对应位置,无合法接入参数会被服务端拒绝。
  • 不要使用setUrl(QtCore.QUrl.fromLocalFile(path))加载本地HTML文件,file://协议的请求会被服务端直接拦截。
  • setHtml必须传入baseUrl参数,否则HTML中所有相对路径的JS、地图瓦片资源都会解析为本地路径导致加载失败。
  • UA修改必须在QApplication实例创建前完成,否则不生效。

内容的提问来源于stack exchange,提问作者E.MRZ

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 13:48:19