【问题标题】:ElementHandle.$eval pageFunction not executedElementHandle.$eval pageFunction 未执行
【发布时间】:2018-07-15 10:26:49
【问题描述】:

我正在使用 Puppeteer 1.6.0 版解析一个 html 表格

// inside the rowMarket variable I store all the rows of a table
rowMarket = await.page.$$('#searchTextResults > tbody > tr');

现在我想遍历所有这些,并为每一行获取一些 td 列的文本。

如果我使用以下代码,一切正常。

for(i=0<rowMarket.length;i++){
  nameComponent = await rowMarket[i].$('td:nth-child(1) > a');
  iT = await nameComponent .getProperty('innerText');
  json = await iT.jsonValue();

  otherComponent = await rowMarket[i].$(' ... ');
  // ... I repeat the same stuff for every column.
}

为了重用一些代码而不是大量复制和粘贴,我定义了下一个函数

async function getContent(element){
  innerText = await element.getProperty('innerText');
  json = await innerText.jsonValue();
  return json;  
}

所以我可以用这种方式重构之前的代码

for(i=0<rowMarket.length;i++){
  nameComponent = await rowMarket[i].$('td:nth-child(1) > a');
  nameText = getContent(nameComponent);

  otherComponent = await rowMarket[i].$(' ... ');
  otherText = getContent(otherComponent);

  // ...
}

但在深入研究文档时,我发现了 $eval function,这似乎是我尝试手工操作的绝佳组合。

接下来我会重构我的代码。我认为它非常干净紧凑。

for(i=0<rowMarket.length;i++){
  nameText = await rowMarket[i].$eval('td:nth-child(1) > a', getContent);
  otherText = await rowMarket[i].$eval(' ...', getContent);
  // ...
}

但我收到下一个错误

(node:8056) UnhandledPromiseRejectionWarning: Error: Evaluation failed: TypeError: elemento.getProperty is not a function
    at dentroElemento (__puppeteer_evaluation_script__:2:30)
    at ExecutionContext.evaluateHandle (c:\webscraping\node_modules\puppeteer\lib\ExecutionContext.js:97:13)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:188:7)

我真的不明白这个错误,因为如果在“独立”模式下调用该函数可以正常工作。

我也试过这个

for(i=0<rowMarket.length;i++){
  nameText = await rowMarket[i].$eval('td:nth-child(1) > a', e => console.log('hello?'));
}

但是 hello 字符串永远不会登录到控制台。所以我认为问题是没有调用 pageFunction 函数。或者我的代码可能有问题。

【问题讨论】:

    标签: javascript puppeteer


    【解决方案1】:

    这:await rowMarket[i].$('td:nth-child(1) &gt; a'); 返回一个 elementHandle。 elementHandle 具有函数.getProperty()。 因此,这就是您的第一个代码有效的原因:

    async function getContent(elementHandle){
      innerText = await elementHandle.getProperty('innerText');
      ...
    

    但是.$evalElement 作为第一个参数传递给您的函数。这与 elementHandle 不同。

    如果你想这样做:nameText = await rowMarket[i].$eval('td:nth-child(1) &gt; a', getContent); 然后你应该重写你的 getContent 函数来处理这样的元素(因为 Element 没有.getProperty() 函数):

    async function getContent(element){
      innerText = await element.innerText;
    

    【讨论】:

    • 它有效。我也注意到(我不知道为什么),该函数内的控制台日志语句没有被记录。这让我觉得即使使用nameText = await rowMarket[i].$eval('td:nth-child(1) &gt; a', e =&gt; console.log('hello?')); 也没有调用该函数
    猜你喜欢
    • 2019-03-15
    • 1970-01-01
    • 2011-04-06
    • 1970-01-01
    • 2016-05-24
    • 1970-01-01
    • 2019-12-08
    • 2019-12-02
    • 2017-05-15
    相关资源
    最近更新 更多