微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

木偶-如何根据元素的内部文本选择元素?

如何解决木偶-如何根据元素的内部文本选择元素?

我正在与Puppeteer抓取一堆页面内容不会与class / ids / etc区分。并且在页面之间以不同的顺序显示。因此,我将需要根据其内部文本选择元素。我在下面添加一个简化的示例html:

<table>
<tr>
    <th>Product name</th>
    <td>Shakeweight</td>
</tr>
<tr>
    <th>Product category</th>
    <td>Exercise equipment</td>
</tr>
<tr>
    <th>Manufacturer name</th>
    <td>The Shakeweight Company</td>
</tr>
<tr>
    <th>Manufacturer address</th>
    <td>
        <table>
            <tr><td>123 Fake Street</td></tr>
            <tr><td>Springfield,MO</td></tr>
        </table>
    </td>
</tr>

在此示例中,我将需要刮擦制造商名称和制造商地址。因此,我想我需要根据嵌套的th的内部文本选择适当的tr,并将相关的td刮到同一tr中。请注意,该表的行顺序并不总是相同,并且该表包含的行比此简化示例要多得多,因此我不能仅选择第3和第4个td。

我试图使用XPATH如下基于内部文本选择一个元素,但是它似乎不起作用:

var manufacturerName = document.evaluate("//th[text()='Manufacturer name']",document,null,XPathResult.ANY_TYPE,null)

这甚至不是我需要的数据(这是与此th关联的td),但是我认为这至少是第一步。如果有人可以提供有关策略的输入以按内部文本进行选择,或选择与此主题相关的td,我将非常感激。

解决方法

根据上面答案中的用例说明,这是用例的逻辑:

await page.goto(url,{ waitUntil: 'networkidle2' }); // Go to webpage url

await page.waitFor('table'); //waitFor an element that contains the text

const textDataArr = await page.evaluate(() => {
    const trArr = Array.from(document.querySelectorAll('table tbody tr'));

    //Find an index of a tr row where th innerText equals 'Manufacturer name'
    let fetchValueRowIndex = trArr.findIndex((v,i) => {
        const element = document.querySelector('table tbody tr:nth-child(i+1) th');
        return element.innerText === 'Manufacturer name';
    });

    //If the findex is found return the innerText of td of the same row else returns undefined
    return (fetchValueRowIndex > -1) ? document.querySelector(`table tbody tr:nth-child(${fetchValueRowIndex}+1) td`).innerText : undefined;
});
console.log(textDataArr);
,

这实际上是一个xpath问题,并且不是专门针对puppeteer的,因此该问题可能也有帮助,因为您将需要找到<td>之后的<th> ve找到:XPath:: Get following Sibling

但是您的xpath对我有用。首先,我使用一个辅助函数来迭代所有xpath结果并返回一个数组:

const xpath = (query,context) => {
  let links = [];
  const elements = document.evaluate(query,context || document,null,XPathResult.ANY_TYPE,null);
  let link = elements.iterateNext();
  while(link != null) {
    links.push(link);
    link = elements.iterateNext();
  }

  return links;
};

复制该块并将其粘贴到问题中带有HTML的页面上的Chrome DevTools中,然后运行以下行以查询文档:

xpath('//th[text()="Manufacturer name"]')

那应该返回一个带有一个元素的数组,<th>并在查询中带有该文本。要使其旁边的<td>

xpath('//th[text()="Manufacturer name"]/following-sibling::td')

并获取其内部文本:

xpath('//th[text()="Manufacturer name"]/following-sibling::td')[0].innerText

一旦您能够遵循该模式,您就应该能够使用类似的策略来在puppeteer中获取所需的数据,就像这样:

const puppeteer = require('puppeteer');

const main = async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('http://127.0.0.1:8080/');  // <-- EDIT THIS

  const mfg = await page.$x('//th[text()="Manufacturer name"]/following-sibling::td');
  const prop = await mfg[0].getProperty('innerText');
  const text = await prop.jsonValue();
  console.log(text);

  await browser.close();
}

main();
,

您可以执行以下操作来获取数据:

await page.goto(url,{ waitUntil: 'networkidle2' }); // Go to webpage url

await page.waitFor('table'); //waitFor an element that contains the text

const textDataArr = await page.evaluate(() => {
    const element = document.querySelector('table tbody tr:nth-child(3) td'); // select thrid row td element like so
    return element && element.innerText; // will return text and undefined if the element is not found
});
console.log(textDataArr);
,

一次获取所有内容的简单方法:

let data = await page.evaluate(() => {
  return [...document.querySelectorAll('tr')].reduce((acc,tr,i) => {
    let cells = [...tr.querySelectorAll('th,td')].map(el => el.innerText)
    acc[cells[0]] = cells[1]
    return acc
  },{})
})

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?