Обход сложного DOM и очистка значений

#javascript #dom #web-scraping #puppeteer #innerhtml

#javascript #dom #веб-очистка #кукловод #innerhtml

Вопрос:

Рассмотрим следующую структуру в DOM.

  <div class="bodyCells">
       <div style="foo">
           <div style="foo">
                <div style="foo"> 
                  <div style="foo1"> '1-contains the list of text elements I want to scrape'</div>
                  <div style="foo2"> '2-contains the list of text elements I want to scrape'</div>
                </div>
                <div style="foo"> 
                  <div style="foo3"> '3-contains the list of text elements I want to scrape'</div>
                  <div style="foo4"> '4-contains the list of text elements I want to scrape'</div>
                </div>
           </div>
       </div>
</div>     
  

Используя bodyCells имени класса, мне нужно извлекать данные из каждого из divs по одному (т.Е.) Сначала из 1-го div, затем из следующего div и так далее и сохранять их в отдельных массивах. Как я могу этого добиться? (с использованием puppeteer)

ПРИМЕЧАНИЕ: я пытался использовать имя класса напрямую для достижения этой цели, но он выдает все тексты в одном массиве.Мне нужно получать данные из каждого тега отдельно и хранить их в разных массивах.

Ожидаемый результат:

   array1=["text present within style="foo1" div tag"] 
  array2=["text present within style="foo2" div tag"] 
  array3=["text present within style="foo3" div tag"]
  array4=["text present within style="foo4" div tag"]
  

Это то, что я делал до сих пор:

  var value=[];
value = await page1.evaluate(() =>{
if (!window.document){window.document = {};}
var textitems=[]
var extracted_items=[]
textitems = document.getElementsByClassName("bodyCells");
for (var i = 0; i < textitems.length; i  ) {
  item=textitems[i].textContent
  extracted_items.push(item);
}
  return extracted_items;
});
  

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

1. для (const div текстовых элементов[0].querySelectorAll(«div»)) { console.log(div); }

2. Мне нужно хранить значения каждого div в отдельных массивах. Как мне это сделать? @gillall

3. Попробуйте этот внутренний цикл: if (/[0-9a-zA-Z]/.test(div.childNodes[0].data)) result.push([div.childNodes[0].data]). Но это подходит только для ваших данных. Вы должны использовать идентификаторы, классы и теги, если хотите легко выполнять очистку

Ответ №1:

Не уверен, что это то, что вам нужно…

 const html = `
  <!doctype html>
  <html>
    <head><meta charset="UTF-8"><title>Test</title></head>
    <body>
      <div class="bodyCells">
        <div style="foo">
          <div style="foo">
            <div style="foo">
              <div style="foo1"> '1-contains the list of text elements I want to scrape'</div>
              <div style="foo2"> '2-contains the list of text elements I want to scrape'</div>
            </div>
            <div style="foo">
              <div style="foo3"> '3-contains the list of text elements I want to scrape'</div>
              <div style="foo4"> '4-contains the list of text elements I want to scrape'</div>
            </div>
          </div>
        </div>
      </div>
    </body>
  </html>`;

const puppeteer = require('puppeteer');

(async function main() {
  try {
    const browser = await puppeteer.launch();
    const [page] = await browser.pages();

    await page.goto(`data:text/html,${html}`);

    const data = await page.evaluate(() => Array.from(
      document.querySelectorAll('div.bodyCells > div > div > div > div'),
      div => [div.innerText],
    ));

    console.log(data);

    await browser.close();
  } catch (err) {
    console.error(err);
  }
})();
  

Вывод:

 [
  [ "'1-contains the list of text elements I want to scrape'" ],
  [ "'2-contains the list of text elements I want to scrape'" ],
  [ "'3-contains the list of text elements I want to scrape'" ],
  [ "'4-contains the list of text elements I want to scrape'" ]
]