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

Chrome扩展接收Django JSON返回undefined及popup渲染问题排查

问题原因

弹窗显示undefined是三个代码问题导致的:

  • 后端返回JSON结构不统一:
    1. 触发验证码判断时,直接返回字符串类型的URL,不存在summary字段
    2. 非验证码分支中,parsefile()函数最后返回的是Products字典,你在函数里临时定义的带summary字段的data变量根本没有被返回,实际响应里没有summary这个key
  • Manifest V3跨域权限配置错误:你把本地后端地址写在了permissions数组里,MV3的跨域请求必须把对应域名配置到host_permissions中,否则请求会被浏览器拦截,拿不到正常响应
  • 前端没有做响应校验,拿到返回值直接读取summary属性,只要字段不存在就会返回undefined

另外你原来的通知配置缺少必填的message字段,就算请求成功通知也弹不出来。

修复方案

1. 统一后端返回结构

修改两个后端函数,保证所有分支返回的JSON结构固定,都包含summary字段:

def parsefile():
    Products = {}
    Images = {}
    # 保留你原有的价格、链接解析逻辑
    with open('output1.html', 'r', encoding="utf-8") as f:
        html_string = f.read()
    soup = BeautifulSoup(html_string, 'lxml')
    prices = soup.find_all('a', {'class': 'productOffers-listItemOfferPrice'})

    # 提前初始化列表,避免判断key是否存在的冗余逻辑
    Products["Website"] = []
    Products["Link"] = []
    Products["Price"] = []
    for elem in prices:
        oldlink = elem['href']
        full_link = "http://XXXX.de" + oldlink
        Products["Website"].append(full_link)
        Products["Price"].append(elem.get_text().strip())
        Products["Link"].append(full_link)

    listimage = soup.find('img', {'class': 'datasheet-cover-image'})
    Products["Image"] = listimage.get("src") if listimage else ""

    # 直接返回统一结构,保证summary字段存在
    return {
        'summary': Products["Image"] if Products["Image"] else f"共找到{len(Products['Price'])}条价格结果",
        'raw': 'Successful',
        'data': Products
    }

def get_wiki_summary(request):
    query = request.GET.get('topic', None) +" XXXX"
    # 保留你原有的UA、爬取、解析逻辑
    user_agent_list = [
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.1 Safari/605.1.15',
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:77.0) Gecko/20100101 Firefox/77.0',
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36',
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:77.0) Gecko/20100101 Firefox/77.0',
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36',
    ]
    user_agent = random.choice(user_agent_list)
    headers = {'User-Agent': user_agent}
    search_result_list = list(search(query, tld="de", num=1, stop=1, pause=1))
    page = requests.get(search_result_list[0], headers=headers)
    time.sleep(4)
    soup = BeautifulSoup(page.text, "lxml")
    with open("output1.html", "w", encoding="utf-8") as file:
        file.write(str(soup))

    if soup.findAll(text="captcha") :
        # 验证码分支也返回统一结构
        return JsonResponse({
            "summary": "触发人机验证,请稍后重试",
            "raw": "captcha",
            "data": {"jump_url": search_result_list[0]}
        })
    else:
        data = parsefile()
        return JsonResponse(data)

2. 修正Manifest权限配置

把本地后端地址加到host_permissions里,删除无效配置项,保证跨域请求正常:

{
  "name": "Price Comparator",
  "description": "Compare prices across other websites!",
  "version": "1.0",
  "manifest_version": 3,
  "background": {
    "service_worker": "background.js"
  },
  "icons": {
    "16": "images/logo16.png",
    "48": "images/logo48.png",
    "128": "images/logo128.png"
  },
  "action": {
    "default_icon": "images/logo16.png",
    "default_popup": "popup.html"
  },
  "host_permissions": [
    "XXX*",
    "http://127.0.0.1:8000/*"
  ],
  "permissions": [
    "XXX",
    "storage",
    "activeTab",
    "scripting",
    "tabs",
    "identity",
    "notifications"
  ],
  "content_scripts": [
    {
      "matches": [
        "https://www.google.com/*"
      ],
      "css": [
        "main.css"
      ]
    }
  ]
}

注意:原来写在permissions里的http://127.0.0.1:8000/和background是无效配置,直接删掉即可。

3. 优化background.js的请求逻辑

增加错误分支的响应返回,避免前端回调一直挂起:

chrome.runtime.onInstalled.addListener(() => { console.log('Extension is running!'); });

chrome.tabs.onActivated.addListener(function (activeInfo) {
    chrome.tabs.get(activeInfo.tabId, function (tab) {
        y = tab.url;
        console.log("you are here: " + tab.title);
    });
});

chrome.tabs.onUpdated.addListener((tabId, change, tab) => {
    if (tab.active && change.url) {
        console.log("you are here: " + change.url);
    }
});

var serverhost = 'XXXX';

chrome.runtime.onMessage.addListener(
    function (request, sender, sendResponse) {
        var url = serverhost + '/wiki/get_wiki_summary/?topic=' + encodeURIComponent(request.topic);
        console.log(url);
        fetch(url)
            .then(response => {
                if (!response.ok) throw new Error(`接口返回状态码${response.status}`);
                return response.json();
            })
            .then(response => sendResponse({ farewell: response }))
            .catch(error => {
                console.error(error);
                // 请求出错时也给前端返回固定结构
                sendResponse({
                    farewell: {
                        summary: "请求失败:" + error.message,
                        raw: "error",
                        data: {}
                    }
                });
            })
        return true;
    });

4. 修改popup逻辑,实现数据渲染到页面

首先在popup.html里添加结果展示容器,放在你原来的搜索输入框、按钮下面即可:

<div id="result-area" style="min-width: 300px; padding: 8px;"></div>

然后修改popup.js,增加响应校验、页面渲染逻辑,同时修复通知配置:

$(function(){
    $('#keywordsubmit').click(function(){
        var search_topic = $('#keyword').val();
        if (search_topic){
            chrome.runtime.sendMessage(
                {topic: search_topic},
                function(response) {
                    // 先做响应合法性校验
                    if (!response || !response.farewell) {
                        alert("请求无响应,请检查后端服务是否启动");
                        return;
                    }
                    const result = response.farewell;
                    alert(result.summary);

                    // 渲染数据到popup页面
                    const resultContainer = $('#result-area');
                    resultContainer.empty();
                    // 渲染商品图
                    if (result.data.Image) {
                        resultContainer.append(`<img src="${result.data.Image}" style="max-width: 100%; margin-bottom: 8px;">`);
                    }
                    // 渲染价格列表
                    if (result.data.Price && result.data.Price.length > 0) {
                        const priceList = $('<ul style="padding-left: 20px; margin: 0;"></ul>');
                        result.data.Price.forEach((price, idx) => {
                            const link = result.data.Link[idx];
                            priceList.append(`<li style="margin-bottom: 4px;"><a href="${link}" target="_blank">${price}</a></li>`);
                        });
                        resultContainer.append(priceList);
                    }

                    // 修复通知配置,basic类型必须传message字段
                    var notifOptions = {
                        type: "basic",
                        iconUrl: "images/logo48.png",
                        title: "价格查询结果",
                        message: result.summary
                    };
                    chrome.notifications.create('PriceResultNotif', notifOptions);
                });
        }
        $('#keyword').val('');
    });
});

内容的提问来源于stack exchange,提问作者Saad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 02:01:33