如何在JavaScript中结合Selenium使用IndexedDB?
解决Selenium与IndexedDB结合时的
window is not defined错误 问题原因
你遇到的ReferenceError: window is not defined本质是环境不匹配:
- Selenium的Node.js代码运行在Node.js环境,没有浏览器的
window对象 - IndexedDB是浏览器专属API,只能在浏览器页面上下文中运行
直接合并两段代码会让IndexedDB逻辑在Node环境执行,自然找不到window对象。
解决方案
用Selenium的executeScript()方法,把IndexedDB的操作逻辑作为脚本字符串注入到浏览器当前页面中执行,让IndexedDB代码运行在浏览器上下文里。具体步骤:
- 用Selenium完成页面访问和数据提取
- 将提取到的数据传入注入的IndexedDB脚本
- 在浏览器中执行IndexedDB的存储逻辑
修改后的完整代码
const {Builder, By, Key, until} = require("selenium-webdriver"); (async function example(){ let driver = await new Builder().forBrowser('firefox').build(); try { await driver.get('http://www.google.com/ncr'); await driver.findElement(By.name('q')).sendKeys('webdriver', Key.RETURN); await driver.wait(until.titleContains('webdriver'), 1000); // 提取页面数据,这里以页面标题为例 const pageTitle = await driver.getTitle(); // 将IndexedDB操作脚本注入到浏览器中执行 await driver.executeScript((data) => { const indexedDB = window.indexedDB; const request = indexedDB.open("SeleniumDB", 1); request.onerror = function (event) { console.error("Error with indexedDB"); console.error(event); }; request.onupgradeneeded = function () { const db = request.result; // 仅在数据库首次创建时创建对象仓库 if (!db.objectStoreNames.contains("Pages")) { const store = db.createObjectStore("Pages", {keyPath: "id", autoIncrement: true}); store.createIndex("text", ["text"], {unique: false}); } }; request.onsuccess = function () { const db = request.result; const transaction = db.transaction("Pages", "readwrite"); const store = transaction.objectStore("Pages"); store.put({text: data}); transaction.oncomplete = function () { db.close(); }; }; }, pageTitle); // 将提取到的数据作为参数传入脚本 } finally { await driver.quit(); } })();
关键说明
executeScript()的第一个参数是要在浏览器中执行的函数,第二个及以后的参数会传递给这个函数onupgradeneeded事件只会在数据库版本升级或首次创建时触发,添加判断可避免重复创建对象仓库- 提取的数据可以是任意可序列化类型(字符串、对象等),能直接传递到浏览器上下文
内容的提问来源于stack exchange,提问作者sigma5563
相关产品推荐
相关产品推荐

