JS无法访问函数内的全局变量
JS cant access global variable inside function
我正在尝试使用 Node 和 Puppeteer 制作一个简单的网络爬虫来获取 reddit 上帖子的标题,但是我在访问一个全局变量时遇到问题,SUBREDDIT_NAME 仅在一个函数 extractItems() 中。它适用于所有其他功能,但对于那个功能,我必须创建一个具有相同值的局部变量才能工作。
我是否完全误解了 Javascript 中的变量范围?
我已经尝试了所有我能想到的方法,唯一可行的是在 extractedItems() 内部创建一个值为 "news" 的局部变量,否则我什么也得不到。
const fs = require('fs');
const puppeteer = require('puppeteer');
const SUBREDDIT = (subreddit_name) => `https://reddit.com/r/${subreddit_name}/`;
const SUBREDDIT_NAME= "news";
function extractItems() {
const extractedElements = document.querySelectorAll(`a[href*='r/${SUBREDDIT_NAME}/comments/'] h3`);
const items = [];
for (let element of extractedElements) {
items.push(element.innerText);
}
return items;
}
async function scrapeInfiniteScrollItems(
page,
extractItems,
itemTargetCount,
scrollDelay = 1000,
) {
let items = [];
try {
let previousHeight;5
while (items.length < itemTargetCount) {
items = await page.evaluate(extractItems);
previousHeight = await page.evaluate('document.body.scrollHeight');
await page.evaluate('window.scrollTo(0, document.body.scrollHeight)');
await page.waitForFunction(`document.body.scrollHeight > ${previousHeight}`);
await page.waitFor(scrollDelay);
}
} catch(e) { }
return items;
}
(async () => {
// Set up browser and page.
const browser = await puppeteer.launch({
headless: false,
args: ['--no-sandbox', '--disable-setuid-sandbox'],
});
const page = await browser.newPage();
page.setViewport({ width: 1280, height: 926 });
// Navigate to the demo page.
await page.goto(SUBREDDIT(SUBREDDIT_NAME));
// Scroll and extract items from the page.
const items = await scrapeInfiniteScrollItems(page, extractItems, 100);
// Save extracted items to a file.
fs.writeFileSync('./items.txt', items.join('\n') + '\n');
// Close the browser.
await browser.close();
})();
我希望有一个包含 100 个首次找到的标题的文本文件,但只有当我将 subreddit 硬编码到 extractItems() 函数中时它才有效。
问题是 extractItems
函数被转换为字符串(不处理模板文字)并在没有 SUBREDDIT_NAME
变量的页面上下文中执行。
您可以通过执行以下操作来解决此问题:
function extractItems(name) {
const extractedElements = document.querySelectorAll(`a[href*='r/${name}/comments/'] h3`);
const items = [];
for (let element of extractedElements) {
items.push(element.innerText);
}
return items;
}
page.evaluate(`(${extractItems})(${SUBREDDIT_NAME})`)
我正在尝试使用 Node 和 Puppeteer 制作一个简单的网络爬虫来获取 reddit 上帖子的标题,但是我在访问一个全局变量时遇到问题,SUBREDDIT_NAME 仅在一个函数 extractItems() 中。它适用于所有其他功能,但对于那个功能,我必须创建一个具有相同值的局部变量才能工作。
我是否完全误解了 Javascript 中的变量范围?
我已经尝试了所有我能想到的方法,唯一可行的是在 extractedItems() 内部创建一个值为 "news" 的局部变量,否则我什么也得不到。
const fs = require('fs');
const puppeteer = require('puppeteer');
const SUBREDDIT = (subreddit_name) => `https://reddit.com/r/${subreddit_name}/`;
const SUBREDDIT_NAME= "news";
function extractItems() {
const extractedElements = document.querySelectorAll(`a[href*='r/${SUBREDDIT_NAME}/comments/'] h3`);
const items = [];
for (let element of extractedElements) {
items.push(element.innerText);
}
return items;
}
async function scrapeInfiniteScrollItems(
page,
extractItems,
itemTargetCount,
scrollDelay = 1000,
) {
let items = [];
try {
let previousHeight;5
while (items.length < itemTargetCount) {
items = await page.evaluate(extractItems);
previousHeight = await page.evaluate('document.body.scrollHeight');
await page.evaluate('window.scrollTo(0, document.body.scrollHeight)');
await page.waitForFunction(`document.body.scrollHeight > ${previousHeight}`);
await page.waitFor(scrollDelay);
}
} catch(e) { }
return items;
}
(async () => {
// Set up browser and page.
const browser = await puppeteer.launch({
headless: false,
args: ['--no-sandbox', '--disable-setuid-sandbox'],
});
const page = await browser.newPage();
page.setViewport({ width: 1280, height: 926 });
// Navigate to the demo page.
await page.goto(SUBREDDIT(SUBREDDIT_NAME));
// Scroll and extract items from the page.
const items = await scrapeInfiniteScrollItems(page, extractItems, 100);
// Save extracted items to a file.
fs.writeFileSync('./items.txt', items.join('\n') + '\n');
// Close the browser.
await browser.close();
})();
我希望有一个包含 100 个首次找到的标题的文本文件,但只有当我将 subreddit 硬编码到 extractItems() 函数中时它才有效。
问题是 extractItems
函数被转换为字符串(不处理模板文字)并在没有 SUBREDDIT_NAME
变量的页面上下文中执行。
您可以通过执行以下操作来解决此问题:
function extractItems(name) {
const extractedElements = document.querySelectorAll(`a[href*='r/${name}/comments/'] h3`);
const items = [];
for (let element of extractedElements) {
items.push(element.innerText);
}
return items;
}
page.evaluate(`(${extractItems})(${SUBREDDIT_NAME})`)