使用Puppeteer/BeautifulSoup/Selenium均无法获取页面中var doc变量的技术求助
Puppeteer/BeautifulSoup/Selenium均无法获取页面中var doc变量的技术求助
首先,我注意到你的代码和场景存在几个关键问题,咱们一步步来解决:
1. 先修复代码中的致命语法错误和缺失步骤
你提供的Puppeteer代码有两个致命问题,这是你拿不到数据的首要原因:
- 多了一个多余的
});:await page.setViewport({ width: 1280, height: 800 }); });这行末尾的额外});会直接导致代码语法报错,程序终止执行。 - 完全缺失打开目标页面的
page.goto()调用:没有访问目标URL,页面都没加载,当然拿不到任何script内容!
先把这两个问题补上和修正,代码才能正常运行。
2. 分析为什么拿不到var doc的深层原因
从你提供的页面源码片段来看,var doc是内联在script标签里的,但还可能存在这些阻碍:
- 正则匹配能力不足:原正则
/var doc = \{[^}]*\};/g只能匹配单行的对象定义,而你的doc内容跨了多行(比如weight字段包含换行和HTML标签),这个正则会提前终止匹配,拿不到完整的对象。 - 无头浏览器被检测:默认的Puppeteer无头模式会被部分网站识别,导致内容不渲染或script不执行。
- 等待策略不可靠:固定时长的
setTimeout等待,可能页面还没完全加载完成就开始提取内容了。 - 用BeautifulSoup的局限性:它是静态HTML解析工具,不会执行JavaScript,如果这个script是页面加载后动态注入的,BeautifulSoup根本看不到它。
3. 改进后的Puppeteer解决方案
我整理了修复并优化后的代码,解决了上述所有问题:
const puppeteer = require('puppeteer'); const fs = require('fs'); async function scrapeTezData(keyword = "yapay zeka") { let browser; try { browser = await puppeteer.launch({ headless: 'new', // 使用新版无头模式,更接近真实浏览器,不易被反爬识别 args: [ '--no-sandbox', '--disable-setuid-sandbox', '--disable-blink-features=AutomationControlled' // 禁用自动化特征检测 ] }); const page = await browser.newPage(); // 模拟更真实的浏览器请求头 await page.setExtraHTTPHeaders({ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8', 'Accept-Language': 'tr-TR,tr;q=0.8,en-US;q=0.5,en;q=0.3', 'Upgrade-Insecure-Requests': '1' }); await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'); await page.setViewport({ width: 1280, height: 800 }); // 关键:替换成你实际要爬取的目标URL await page.goto('https://你的目标页面URL.com', { waitUntil: 'networkidle2' }); console.log("Waiting for all resources to load..."); // 等待网络空闲3秒,确保所有JS执行完成 await page.waitForNetworkIdle({ idleTime: 3000 }); // 提取script中的var doc内容 const scriptData = await page.evaluate(() => { const scripts = Array.from(document.querySelectorAll('script')); let docBlocks = []; for (const script of scripts) { const content = script.innerHTML.trim(); if (!content) continue; // 过滤包含目标变量的script if (content.includes('var rows = []') && content.includes('var doc =')) { // 匹配跨多行的var doc = { ... }; 用[\s\S]*?匹配任意字符(包括换行),非贪婪模式避免过度匹配 const docRegex = /var doc = \{[\s\S]*?\};/g; const matches = content.match(docRegex); if (matches) { docBlocks.push(...matches); } } } return docBlocks; }); console.log('Successfully extracted doc blocks:', scriptData); // 保存结果到文件 if (scriptData.length > 0) { await fs.promises.writeFile('tezData.json', JSON.stringify(scriptData, null, 2)); console.log('Data saved to tezData.json'); } else { console.log('No doc blocks found - please check if the target page has the expected content'); } } catch (error) { console.error(`Scraping failed: ${error.message}`); console.error('Error stack:', error.stack); } finally { if (browser) { await browser.close(); } } } // 调用爬取函数 scrapeTezData();
4. 其他调试建议
- 把
headless改成false,打开浏览器可视化查看页面加载情况,确认页面是否正常显示了你要的内容。 - 在代码里添加浏览器日志捕获:
page.on('console', msg => console.log('Browser log:', msg.text())),这样可以看到page.evaluate里的console.log输出,方便确认script内容是否和你预期一致。 - 如果用Selenium,也要确保等待页面完全加载,然后提取所有script标签的innerHTML,用同样的正则去匹配内容——不要直接尝试访问
window.doc,因为它可能在script的局部作用域里,不是全局变量。
内容来源于stack exchange
相关产品推荐
相关产品推荐

