繁体   English   中英

如何通过JavaScript / cheerio从以下html中提取文本?

[英]How to extract text from the following html as I want by JavaScript / cheerio?

我想从html提取文本,命名为text.html ,如下所示

<div class="trans-container">
  <ul>
     <p class="wordGroup">
        <span style="font-weight: bold; color: #959595; margin-right: .5em; width : 36px; display: inline-block;">adj.</span>
        <span class="contentTitle"><a class="search-js" href="/w/good/#keyfrom=E2Ctranslation">good</a>
        <span style="font-weight: bold; color: #959595;"> ;</span>
        </span>
        <span class="contentTitle"><a class="search-js" href="/w/fine/#keyfrom=E2Ctranslation">fine</a>
        <span style="font-weight: bold; color: #959595;"> ;</span>
        </span>
        <span class="contentTitle"><a class="search-js" href="/w/ok/#keyfrom=E2Ctranslation">ok</a>
        </span>
     </p>
     <p class="wordGroup">
        <span style="font-weight: bold; color: #959595; margin-right: .5em; width : 36px; display: inline-block;">adv.</span>
        <span class="contentTitle"><a class="search-js" href="/w/well/#keyfrom=E2Ctranslation">well</a>
        </span>
     </p>
     <p class="wordGroup">
        <span style="font-weight: bold; color: #959595; margin-right: .5em; width : 36px; display: inline-block;">misc.</span>
        <span class="contentTitle"><a class="search-js" href="/w/all right/#keyfrom=E2Ctranslation">all right</a>
        </span>
     </p>
  </ul>
</div>

并按以下格式打印出来。

adj. good ; fine ; ok
adv. well
misc. all right

我试过的是下面的代码

const cheerio = require('cheerio');
const fs = require('fs');

const $ = cheerio.load(fs.readFileSync('./test.html'));
$('div.trans-container').find('p.wordGroup').each(function(i,elm){
  const line = []
  $(this).find('span').each(function(i,elm){
    line[i] = $(this).text().trim()
  })
  console.log(line.join(' '))
});

不幸的是,我们的输出如下,而不完全是我想要的。 谁能帮我指出我错了吗? 此外,将不胜感激,如果你能为我提供其他体面的方式由JavaScript,有无Cheerio不管来解决这个问题。

adj. good
         ; ; fine
         ; ; ok
adv. well
misc. all right

这也许是您正在寻找的解决方案

line[i] = $(this).children().length > 0 ? $(this).children(":first-child").text().trim() : $(this).text().trim();

这给出了预期的输出。 这将检查此节点是否具有子节点并仅获取第一个节点文本。 如果没有子节点,则只需提取节点文本。

http://api.jquery.com/text/上有关jquery text()函数的官方文档说

获取匹配元素集合中每个元素的组合文本内容(包括它们的后代),或设置匹配元素的文本内容。

另一个相关的帖子是这个https://stackoverflow.com/a/32170000/578855

如果为每个<p>标记提供一个ID,则可以使用此脚本访问您的子元素并从中获取值:

var adjElements = document.getElementById("adj").children;
var advElements = document.getElementById("adv").children;
var miscElements = document.getElementById("misc").children;
var adjObject =[];
var advObject =[];
var miscObject =[];


for (var i=0; i<=adjElements.length -1; i++){
    adjObject.push(adjElements[i].innerText);
}

for (var i=0; i<=advElements.length -1; i++){
    advObject.push(advElements[i].innerText);
}

for (var i=0; i<=miscElements.length -1; i++){
    miscObject.push(miscElements[i].innerText);
}

console.log(adjObject); //["adj.", "good ; ", "fine ; ", "ok"]
console.log(advObject); //["adv.", "well"]
console.log(miscObject); //  ["misc.", "all right"]

我为你举例:

https://jsfiddle.net/37g6ture/2/

记住要在p标签中添加adjadvmisc ID。

您的主要问题是双循环。 内部的$(this).find('span').each导致一些跨度被迭代两次。 例如:

<span class="contentTitle">
    <a class="search-js" href="/w/fine/#keyfrom=E2Ctranslation">fine</a>
    <span style="font-weight: bold; color: #959595;"> ;</span>
</span>

<span class="contentTitle">上调用span.text()将返回span.text() fine ; 然后还对内部跨度<span style="font-weight: bold; color: #959595;">进行迭代,并添加第二个; 其次,如果您的目标是删除所有多余的空格,但只保留一个空格,则可以使用.replace(/\\s\\s+/g, ' '))

整个代码:

const $ = require('cheerio').load(require('fs').readFileSync('./test.html'));
$('div.trans-container').find('p.wordGroup').each(function(i,elm){
  console.log($(this).text().replace(/\s\s+/g, ' '));
});

导致

adj. good ; fine ; ok 
adv. well 
misc. all right 

在这种情况下, .wordGroup在主要组.wordGroup上使用text() ,它将获得该元素的所有文本而没有html元素。 然后在其上运行replace() ,以单个空格删除所有空白字符。

$('div.trans-container').find('p.wordGroup').each(function(i,elm){
  // regex: /\s+/g matches 1 or more whitespace characters \n\r\f\t
  var line = $(this).text().replace(/\s+/g," ");
  console.log(line);
});

至于仅使用本机javascript,您就不能使用Node.js,因为它不具有本机DOM支持。 因此,您必须使用诸如cheerio或jsdom之类的模块。 如果您的意思是在浏览器中使用javascript,则可能是:

document.querySelectorAll('div.trans-container p.wordGroup')
  .forEach(ele=>console.log( ele.innerText.replace(/\s+/g," ") ));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM