извлечение данных JSON из анонимной функции с помощью puppeteer

#puppeteer

#puppeteer

Вопрос:

Веб-страница, которую я очищаю, содержит следующее содержимое:

 <html>
  <head></head>
  <body>
    <span id="an_id">
      <script type="text/javascript">

var foo = "";

$(function(){$('#bar').something(
  {
    data: [
      { title: 'x', description:'x_desc' },
      { title: 'y', description:'y_desc' }
    ],
    whatever: 1
  });}
);
      </script>
    </span>
  </body>
</html>
  

Мне нужно получить данные в массиве, поэтому меня это интересует:

 [
  { title: 'x', description:'x_desc' },
  { title: 'y', description:'y_desc' }
]
  

Я пытался использовать page.evaluate() and page.queryObjects() , но безрезультатно, я просто недостаточно хорошо это понимаю.

Кто-нибудь, кто мог бы указать мне правильное направление?

Редактировать:

Я взломал это вместе, но это настолько противно, что меня тошнит:

 const page = await browser.newPage();
await page.goto('file://C:/tmp/test.htm');

await page.waitForSelector("#an_id")

const scriptContents = await page.$eval('#an_id', e => e.innerHTML);

console.log(`scriptContents: ${scriptContents}`)

const startDelimiter = "data:"
const endDelimiter = "whatever: 1"

const startDelimiterIndex = scriptContents.indexOf(startDelimiter)   startDelimiter.length;
const endDelimiterIndex  = scriptContents.indexOf(endDelimiter);
const rawData = scriptContents.substring(startDelimiterIndex, endDelimiterIndex).trim().slice(0, -1);

console.log(`rawData: --${rawData}--`)

const data = eval(rawData);
console.log(`data:`)
console.log(data)

console.log(`the description of y: ${data[1].description}`)

await browser.close();
  

Что приводит к:

 scriptContents: 
      <script type="text/javascript">

var foo = "";

$(function(){$('#bar').something(
  {
    data: [
      { title: 'x', description:'x_desc' },
      { title: 'y', description:'y_desc' }
    ],
    whatever: 1
  });}
);
      </script>
    
rawData: --[
      { title: 'x', description:'x_desc' },
      { title: 'y', description:'y_desc' }
    ]--
data:
[ { title: 'x', description: 'x_desc' },
  { title: 'y', description: 'y_desc' } ]
the description of y: y_desc
  

Должен быть лучший способ 🙂

Ответ №1:

Похоже, это должно сделать это (непроверено):

 await page.evaluate(() => {
  let html = document.querySelector('#an_id script').innerHTML
  return html.match(/[.*]/s)[0]
})
  

Комментарии:

1. Это не лучше / чище, чем мое решение, это просто сопоставление чего-либо между квадратными скобками, что в точности совпадает с сопоставлением с моими startDelimiter и endDelimiter, единственное отличие заключается в том, что вы используете строку iso регулярного выражения, соответствующую данным JSON, в которой, вероятно, будет больше квадратных скобок вв моем случае (не в примере) это не сработало бы с вашим решением. Для меня это не является более чистым / лучшим решением, извините 🙂