JS не может получить доступ к глобальной переменной внутри функции - PullRequest
0 голосов
/ 24 июня 2019

Я пытаюсь создать простой веб-браузер, использующий Node и Puppeteer для получения заголовков сообщений в reddit, но у меня возникают проблемы с доступом к глобальной переменной SUBREDDIT_NAME только из одной функции extractItems ().Он отлично работает с любой другой функцией, но для этого мне нужно создать локальную переменную с тем же значением, чтобы она работала.

Полностью ли я неправильно понимаю область видимости переменной в Javascript?

IЯ перепробовал все, что только могу придумать, и единственное, что работает, - это создать локальную переменную внутри extractItems () со значением «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 первыми найденными заголовками, но он работает только тогда, когда я жестко закодировал субредит в функцию extractItems ().

1 Ответ

2 голосов
/ 24 июня 2019

Проблема в том, что функция 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})`)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...