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

Chrome扩展调用本地Python脚本报错“ReferenceError: $ is not defined”求助

解决Chrome扩展的jQuery未定义错误与本地Python脚本调用问题

先解决你碰到的ReferenceError: $ is not defined错误,然后再梳理Chrome扩展调用本地Python脚本的核心问题——你的现有思路存在本质缺陷:Chrome扩展无法直接通过AJAX调用本地文件系统里的Python脚本,得用官方支持的方式实现。


一、修复jQuery未定义错误

这个错误出现在content.js里,根源是内容脚本(content script)的执行环境和页面完全隔离,你在popup.html里引入的jQuery不会自动作用到内容脚本中;另外popup.html里重复引入jQuery的问题也需要清理。

具体修正步骤:

  1. 清理popup.html的脚本引入:
    删除本地jquery-3.5.1.min.js的引入(如果没有这个本地文件的话),保留CDN版本即可,同时调整脚本顺序,确保先加载jQuery再加载依赖它的脚本:

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Scraper</title>
    </head>
    <body>
      <button>Run Python</button>
      <!-- 先引入jQuery -->
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
      <!-- popup.js依赖jQuery,放在后面 -->
      <script src="popup.js"></script>
      <!-- content.js是内容脚本,不需要在这里引入!它会通过manifest自动注入到目标页面 -->
    </body>
    </html>
    
  2. 给内容脚本添加jQuery依赖:
    修改manifest.json的content_scripts配置,把jQuery也注入到目标页面中,这样content.js就能正常使用$了:

    "content_scripts": [
      {
        "matches": ["https://www.amazon.in/*"],
        "js": ["https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js", "content.js"]
      }
    ],
    

    (如果需要离线使用扩展,建议下载jQuery文件到本地,替换上述CDN路径)


二、核心问题:Chrome扩展调用本地Python脚本的正确方式

你原来写的$.ajax({url: "./myscraper"})完全行不通——Chrome扩展的AJAX请求只能发送到HTTP/HTTPS服务器,无法直接访问本地文件系统里的脚本。这里提供两种可行的实现方案:

方案1:用Native Messaging(官方推荐,适合桌面端)

Native Messaging是Chrome官方提供的扩展与本地应用通信的方式,步骤如下:

  1. 修改Python脚本:让它从标准输入读取Chrome发送的URL,处理后把JSON结果输出到标准输出(遵循Native Messaging的通信规范):

    from bs4 import BeautifulSoup as soup
    import requests
    import json
    import sys
    import struct
    
    # 读取Chrome发送的Native Messaging格式消息
    def read_message():
        raw_length = sys.stdin.read(4)
        if not raw_length:
            sys.exit(0)
        message_length = struct.unpack('=I', raw_length)[0]
        message = sys.stdin.read(message_length)
        return json.loads(message)
    
    # 向Chrome发送Native Messaging格式消息
    def send_message(message):
        encoded_message = json.dumps(message).encode('utf-8')
        sys.stdout.write(struct.pack('=I', len(encoded_message)))
        sys.stdout.write(encoded_message)
        sys.stdout.flush()
    
    # 网页抓取逻辑
    def scrape_amazon(url):
        header = { "User-Agent":'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36' }
        page = requests.get(url, headers=header)
        page_soup = soup(page.content,'html.parser')
        title = page_soup.find(id="productTitle").get_text()
        price = page_soup.find(id="priceblock_ourprice").get_text()
        available = page_soup.find(id="availability").get_text()
        avail = available.split(".")
        availability = avail[0]
        return {
            'NAME': title.strip(),
            'PRICE': price.strip(),
            'AVAILABILITY': availability.strip(),
        }
    
    if __name__ == "__main__":
        message = read_message()
        url = message.get('url')
        result = scrape_amazon(url)
        # 保存结果到本地JSON(可选)
        with open('amazon.json','w') as json_file:
            json.dump(result, json_file)
        # 把结果发送回Chrome扩展
        send_message(result)
    
  2. 创建Native Messaging主机配置文件(比如命名为com.yourname.scraper.json),注意替换路径和扩展ID:

    {
      "name": "com.yourname.scraper",
      "description": "Amazon Scraper Native Messaging Host",
      "path": "你的Python脚本绝对路径",
      "type": "stdio",
      "allowed_origins": [
        "chrome-extension://<你的扩展ID>/"
      ]
    }
    

    (扩展ID可以在Chrome扩展管理页面开启开发者模式后查看)

  3. 注册Native Messaging主机:

    • Windows:在注册表HKEY_CURRENT_USER\Software\Google\Chrome\NativeMessagingHosts\com.yourname.scraper中添加项,值为上述配置文件的绝对路径。
    • macOS:把配置文件放到~/Library/Application Support/Google/Chrome/NativeMessagingHosts/目录。
    • Linux:把配置文件放到~/.config/google-chrome/NativeMessagingHosts/目录。
  4. 修改扩展代码调用Native Messaging:

    • 更新popup.js:
      document.addEventListener('DOMContentLoaded', function() {
          document.querySelector('button').addEventListener('click', onclick, false)
          function onclick() {
              chrome.tabs.query({currentWindow:true, active:true}, function(tabs){
                  var link = tabs[0].url;
                  // 调用Native Messaging主机
                  chrome.runtime.sendNativeMessage('com.yourname.scraper', {url: link}, function(response) {
                      if (chrome.runtime.lastError) {
                          alert('调用失败:' + chrome.runtime.lastError.message);
                      } else {
                          alert('抓取结果:\n' + JSON.stringify(response, null, 2));
                      }
                  });
              })
          }
      }, false)
      
    • 更新manifest.json添加权限:
      "permissions": ["activeTab", "nativeMessaging"],
      

方案2:把Python脚本做成本地HTTP服务器(更简单易上手)

如果觉得Native Messaging配置太繁琐,可以把Python脚本改成一个轻量HTTP服务器,扩展通过AJAX请求这个服务器:

  1. 修改Python脚本为Flask服务器:

    from bs4 import BeautifulSoup as soup
    import requests
    import json
    from flask import Flask, request
    
    app = Flask(__name__)
    
    @app.route('/scrape', methods=['POST'])
    def scrape():
        url = request.json.get('url')
        header = { "User-Agent":'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36' }
        page = requests.get(url, headers=header)
        page_soup = soup(page.content,'html.parser')
        title = page_soup.find(id="productTitle").get_text()
        price = page_soup.find(id="priceblock_ourprice").get_text()
        available = page_soup.find(id="availability").get_text()
        avail = available.split(".")
        availability = avail[0]
        result = {
            'NAME': title.strip(),
            'PRICE': price.strip(),
            'AVAILABILITY': availability.strip(),
        }
        with open('amazon.json','w') as json_file:
            json.dump(result, json_file)
        return json.dumps(result)
    
    if __name__ == '__main__':
        app.run(host='localhost', port=5000, debug=True)
    

    (需要先安装Flask:pip install flask)

  2. 修改扩展的popup.js发送请求:

    document.addEventListener('DOMContentLoaded', function() {
        document.querySelector('button').addEventListener('click', onclick, false)
        function onclick() {
            chrome.tabs.query({currentWindow:true, active:true}, function(tabs){
                var link = tabs[0].url;
                $.ajax({
                    url: 'http://localhost:5000/scrape',
                    method: 'POST',
                    contentType: 'application/json',
                    data: JSON.stringify({url: link}),
                    success: function(response) {
                        alert('抓取结果:\n' + JSON.stringify(response, null, 2));
                    },
                    error: function(err) {
                        alert('请求失败,请确保Python服务器已启动:' + err.responseText);
                    }
                });
            })
        }
    }, false)
    
  3. 更新manifest.json添加权限:

    "permissions": ["activeTab", "http://localhost:5000/*"],
    

最后注意事项

  • 如果你打算升级到Manifest V3(Chrome当前推荐的版本),部分API会有变化,比如browser_action改成action,content_security_policy格式也需要调整,需要对应适配。
  • 运行前请确保Python脚本的依赖(BeautifulSoup、requests、Flask等)已经安装完成。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 22:52:52