Javascript 当只有$eval给出结果($$返回未定义)时,如何获取所有innerHTML

Javascript 当只有$eval给出结果($$返回未定义)时,如何获取所有innerHTML,javascript,web-scraping,puppeteer,Javascript,Web Scraping,Puppeteer,有一个表,我试图从每一行提取3个信息。一旦完成,它将滚动到页面底部,单击“加载更多”,然后刮取新数据,依此类推,直到没有更多的“加载更多”按钮 为了从表中提取所有数据,我使用了$$eval,但这会导致未定义的错误。但是,如果使用$eval,我会得到数据,但这只会从表的第一行提取数据。为什么$$eval返回“undefined”,如果我不能使用它,我如何在表中循环以使用$eval获取所有值 const puppeteer = require('puppeteer'); (async ()

有一个表,我试图从每一行提取3个信息。一旦完成,它将滚动到页面底部,单击“加载更多”,然后刮取新数据,依此类推,直到没有更多的“加载更多”按钮

为了从表中提取所有数据,我使用了$$eval,但这会导致未定义的错误。但是,如果使用$eval,我会得到数据,但这只会从表的第一行提取数据。为什么$$eval返回“undefined”,如果我不能使用它,我如何在表中循环以使用$eval获取所有值

    const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({ headless: false }); // default is true
  const page = await browser.newPage();
  await page.goto('someexamplesite.com', {
    waitUntil: 'domcontentloaded',
  });

  const ExerciseName = await page.$$eval(
    '.ExCategory-results > .ExResult-row:nth-child(2) > .ExResult-cell > .ExHeading > a',
    (e) => e.innerText
  );

  const muscleTargeted = await page.$$eval(
    ' .ExCategory-results > .ExResult-row:nth-child(2) > .ExResult-cell > .ExResult-muscleTargeted > a',
    (e) => e.innerText
  );

  const equipmentType = await page.$$eval(
    '.ExCategory-results > .ExResult-row:nth-child(2) > .ExResult-cell > .ExResult-equipmentType > a',
    (e) => e.innerText
  );

  //click on load more
  await page.waitForSelector(
    '#js-ex-content > #js-ex-category-body > .ExCategory-results > .ExLoadMore > .bb-flat-btn'
  );

  console.log({ ExerciseName, muscleTargeted, equipmentType });

    await browser.close();
})().catch((e) => {
  console.error(e);
});
我正试图删除的代码

<div class="ExCategory-results">
    <div class="ExCategory-resultsLoadIndicator" id="js-ex-finder-load-indicator">
      <div class="ExCategory-resultsLoadIndicatorBox">
        <div class="ExCategory-resultsLoadIndicatorSpinner bb-spinner-btn__spinner"></div>
      </div>
    </div>
        
          <div class="ExResult-row  flexo-container flexo-between" itemscope="" itemtype="http://schema.org/ExerciseAction">
            <div class="ExResult-cell ">
                <!-- using male photos -->
                <img class="ExImg ExResult-img  ls-is-cached lazyloaded" width="70" height="70" onerror="if (window._E_) _E_(this)" alt=" thumbnail image" src="https://www.websites.com/exercises/exerciseImages/sequences/742/Male/m/742_1.jpg" data-src="https://www.websites.com/exercises/exerciseImages/sequences/742/Male/m/742_1.jpg" itemprop="image">
            </div>
            <div class="ExResult-cell ExResult-cell--nameEtc">
              <h3 class="ExHeading ExResult-resultsHeading">
                <a href="/exercises/rickshaw-carry" itemprop="name">
                  Rickshaw Carry
                </a>
              </h3>
              <div class="ExResult-details ExResult-muscleTargeted">
                Muscle Targeted:
                <a href="/exercises/muscle/forearms">
                  Forearms
                </a>
              </div>
              <div class="ExResult-details ExResult-equipmentType">
                Equipment Type:
                <a href="/exercises/equipment/other">
                  Other
                </a>
              </div>
            </div>
            <div class="ExResult-cell ExResult-cell--rating">
              <div class="ExRating">
                <div class="ExRating-badge">
                  9.6
                </div>
                <div class="ExRating-description ExRating-description--Average">
                  Average
                </div>
              </div>
            </div>
          </div>        
        
          <div class="ExResult-row  flexo-container flexo-between" itemscope="" itemtype="http://schema.org/ExerciseAction">
            <div class="ExResult-cell ">
                <!-- using male photos -->
                <img class="ExImg ExResult-img  ls-is-cached lazyloaded" width="70" height="70" onerror="if (window._E_) _E_(this)" alt=" thumbnail image" src="https://www.websites.com/images/2020/xdb/cropped/xdb-50m-single-leg-leg-press-m1-square-600x600.jpg" data-src="https://www.websites.com/images/2020/xdb/cropped/xdb-50m-single-leg-leg-press-m1-square-600x600.jpg" itemprop="image">
            </div>
            <div class="ExResult-cell ExResult-cell--nameEtc">
              <h3 class="ExHeading ExResult-resultsHeading">
                <a href="/exercises/single-leg-press" itemprop="name">
                  Single-Leg Press
                </a>
              </h3>
              <div class="ExResult-details ExResult-muscleTargeted">
                Muscle Targeted:
                <a href="/exercises/muscle/quadriceps">
                  Quadriceps
                </a>
              </div>
              <div class="ExResult-details ExResult-equipmentType">
                Equipment Type:
                <a href="/exercises/equipment/machine">
                  Machine
                </a>
              </div>
            </div>
            <div class="ExResult-cell ExResult-cell--rating">
              <div class="ExRating">
                <div class="ExRating-badge">
                  9.6
                </div>
                <div class="ExRating-description ExRating-description--Average">
                  Average
                </div>
              </div>
            </div>
          </div>        

肌肉目标:
设备类型:
9.6
平均值
肌肉目标:
设备类型:
9.6
平均值
该方法在后台运行
Array.from(document.querySelectorAll(selector))
,因此得到的是一个数组。如果不迭代数组或通过适当的索引获取正确的元素(例如:
e[0].innerText
),则无法直接在数组上应用
(e)=>e.innerText
(即使其长度为
1
),否则将得到
未定义的

可以使用对匹配元素进行迭代,并将每个元素的
innerText
收集到一个数组中

const exerciseName=等待页面。$$eval(
“.excategority results>.ExResult行:第n个孩子(2)>.ExResult单元格>.ExHeading>a”,
elements=>elements.map(el=>el.innerText)
)
输出:

[“人力车运输”]

编辑:

通过(1)计算具有相同类名的元素,您可以使用带有索引的循环(最容易使用常规
for
循环)迭代行类:

const rowsconts=wait page.$$eval('.ExCategory results>.ExResult row',rows=>rows.length)
然后(2)迭代子项
.ExResult行:第n个子项(n).
,并将
内部文本
收集到一个数组(
exerciseNames
):

const exerciseNames=[]
对于(设i=1;i.ExResult行:第n个子(${i})>.ExResult单元格>.ExHeading>a`,
el=>el.innerText)
exerciseName.push(exerciseName)
}
输出:

[
“人力车运输”,
“单腿压力机”,
“地雷扭曲”,
“加权上拉”,
“带把手的T形杆行”,
“手掌向下,手腕在长凳上卷曲”
]

注意:在这种情况下,循环应该从
1
开始,而不是
0
,因为没有“第n个子(0)”。在您的示例中,第1个也丢失了,因此您可能需要从
2

开始迭代。谢谢您,我还发布了一段代码片段,我正在尝试将其删除。您能否显示出出错的部分,而不是有效的部分?如果
$$eval
失败,请显示您正在使用的无效代码,以便我们可以告诉您可能做错了什么。另外,请记住,如果您要包含代码,请尝试使其成为一个示例,因为现在您显示了大量的JS和标记,超出了显示问题所需的范围。我用$$eval更新了它。我不知道我想把多少页刮到过去。下一次我就发两段,谢谢!既然$$eval执行querySelectorAll,我如何让它返回表的所有内部文本?这与
querySelector
querySelectorAll
的关系不大,因为行是彼此的兄弟行,所以它们不共享同一个选择器()。您似乎需要
页面。$eval
在循环中。用一个例子看我更新的答案。我现在更了解这一点&这很有效。非常感谢。固定的!innerHTML解决了这个问题。它确实添加了一些不需要的字符,如“\n”,但这些字符可以在excel中修复。很高兴听到您能够解决它。您可以在javascript代码中使用string.replace()清除换行符(即\n-s)和其他不需要的模式的结果