【问题标题】:Scraping Text as rendered in browser抓取浏览器中呈现的文本
【发布时间】:2023-03-07 21:27:01
【问题描述】:

我正在尝试使用 innerText 属性从 html 中提取文本,如下所示: console.log(document.getElementById('row').innerText)

但是,输出的方式与我在浏览器上看到的方式不同。

差异的原因是第一种情况的表格元素包含inline-block的样式(见下文)。

我该如何解决这个问题,以便获得与浏览器中显示的格式相同的文本?

情况#1: 输入:

<html>
   <body id='test'>
      <table style="display: inline-block">
         <tr>
            <td>1</td>
         </tr>
         <tr>
            <td>2</td>
         </tr>
      </table>
      <table style="display: inline-block">
         <tr>
            <td>3</td>
         </tr>
         <tr>
            <td>4</td>
         </tr>
      </table>
   </body>
</html>

预期输出:

1 3
2 4

实际输出

1
2
3
4

情况#2: 输入:

<html>
   <body id='test'>
      <table>
         <tr>
            <td>1</td>
         </tr>
         <tr>
            <td>2</td>
         </tr>
      </table>
      <table>
         <tr>
            <td>3</td>
         </tr>
         <tr>
            <td>4</td>
         </tr>
      </table>
   </body>
</html>

预期输出:

1 
2 
3
4

实际输出

1
2
3
4

【问题讨论】:

  • 您没有任何#row 元素,因此您的console.log(document.getElementById('row').innerText) 会引发错误。
  • 您能否分享您的 Javascript 代码,以便我们更好地了解您迄今为止所做的尝试。?
  • @JamesGarcia 他做到了,问题的第二行(尽管#row 看起来可能只是一个错字)
  • 是的,row 是一个错字,应该是“test”。我基本上是在尝试获取整个html的文本
  • 您将获得 id=test 元素内的所有文本,因为它以文档顺序 (1, 2, 3, 4) 显示,因为这就是 innerText 所做的——您无法获得除非 也渲染它,否则它会在页面中呈现,这将需要您完全解析 HTML 和样式,或者至少遍历 DOM 树并应用样式。

标签: javascript web-scraping innertext


【解决方案1】:

虽然看起来应该有更简单的方法,但 DOM 不理解可见顺序,因此您可能必须手动转置值,例如:

    // Populates domOrder from DOM (Note: These example selectors are fragile)
    const domOrder = [], visibleOrder = [];
    // Uses spread operator to get an array of tables
    const inlineTables = [...document.querySelectorAll("table")]
      .filter(table => table.style.display == "inline-block")
        .forEach(table => {
          // Gets rows
          [...table.children]
            // I'm not certain whether splitting on newlines is always reliable
            .forEach(tr => domOrder.push(tr.innerText.split(/\n/g)));
        });
    // Populates visibleOrder by transposing values from domOrder
    const rowCount = domOrder.length;
    const colCount = domOrder[0].length;
    domOrder[0].forEach( (col, colNum) => { 
      // Adds a row to visibleOrder
      visibleOrder[colNum] = []; 
      // Transposes the values 
      domOrder.forEach( (row, rowNum) => {
        visibleOrder[colNum][rowNum] = domOrder[rowNum][colNum];
      });
    });
    console.log(visibleOrder);
    <table style="display: inline-block">
       <tr><td>1</td></tr>
       <tr><td>2</td></tr>
    </table>
    <table style="display: inline-block">
       <tr><td>3</td></tr>
       <tr><td>4</td></tr>
    </table>
    <table style="display: inline-block">
       <tr><td>5</td></tr>
       <tr><td>6</td></tr>
    </table>

这里有一个更强大的 matrix transposition 示例。

【讨论】:

  • 问题是我试图找到一个强大的解决方案来考虑所有不同的样式。如果表格具有 inline-block 样式但在其他情况下会中断,则您的解决方案可以正常工作。例如,如果表格没有“inline-block”样式,而是一个表格有“align=left”,另一个表格有“align=right”,则解决方案不起作用。谢谢你的帮助。在我开始自己编写代码之前,我只是想确保没有简单的解决方案。
猜你喜欢
  • 2013-09-14
  • 1970-01-01
  • 2015-02-14
  • 1970-01-01
  • 2016-01-14
  • 2019-09-15
  • 2010-10-15
  • 1970-01-01
  • 2023-03-07
相关资源
最近更新 更多