如何通过 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[=27],我将不胜感激=].
adj. good
; ; fine
; ; ok
adv. well
misc. all right
这也许就是您正在寻找的解决方案
line[i] = $(this).children().length > 0 ? $(this).children(":first-child").text().trim() : $(this).text().trim();
这给出了预期的输出。这将检查此节点是否有子节点并仅获取第一个节点文本。如果没有子节点,则只提取节点文本。
关于 jquery text() 函数的官方文档在 http://api.jquery.com/text/ 说
Get the combined text contents of each element in the set of matched
elements, including their descendants, or set the text contents of the
matched elements.
另一个相关的post是这个
如果您为每个 <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/
记得将 adj
、adv
和 misc
ID 添加到您的 p 标签。
只需在主组上使用text()
,在这种情况下.wordGroup
,它会得到没有html元素的元素的所有文本。然后 运行 上的 replace()
删除所有白色 space 字符和单个 space。
$('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 就无法使用 Nodejs,因为它没有本机 DOM 支持。所以你必须使用像 cheerio 或 jsdom 这样的模块。如果你的意思是 javascript 在浏览器中它会像:
document.querySelectorAll('div.trans-container p.wordGroup')
.forEach(ele=>console.log( ele.innerText.replace(/\s+/g," ") ));
您的主要问题是双循环。内部 $(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()
将 return fine ;
然后,内部跨度 <span style="font-weight: bold; color: #959595;">
也被迭代,添加第二个 ;
。
其次,如果你的目标是去除所有多余的白色 space,但只留下一个,这会起作用 .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
我想从 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[=27],我将不胜感激=].
adj. good
; ; fine
; ; ok
adv. well
misc. all right
这也许就是您正在寻找的解决方案
line[i] = $(this).children().length > 0 ? $(this).children(":first-child").text().trim() : $(this).text().trim();
这给出了预期的输出。这将检查此节点是否有子节点并仅获取第一个节点文本。如果没有子节点,则只提取节点文本。
关于 jquery text() 函数的官方文档在 http://api.jquery.com/text/ 说
Get the combined text contents of each element in the set of matched elements, including their descendants, or set the text contents of the matched elements.
另一个相关的post是这个
如果您为每个 <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/
记得将 adj
、adv
和 misc
ID 添加到您的 p 标签。
只需在主组上使用text()
,在这种情况下.wordGroup
,它会得到没有html元素的元素的所有文本。然后 运行 上的 replace()
删除所有白色 space 字符和单个 space。
$('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 就无法使用 Nodejs,因为它没有本机 DOM 支持。所以你必须使用像 cheerio 或 jsdom 这样的模块。如果你的意思是 javascript 在浏览器中它会像:
document.querySelectorAll('div.trans-container p.wordGroup')
.forEach(ele=>console.log( ele.innerText.replace(/\s+/g," ") ));
您的主要问题是双循环。内部 $(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()
将 return fine ;
然后,内部跨度 <span style="font-weight: bold; color: #959595;">
也被迭代,添加第二个 ;
。
其次,如果你的目标是去除所有多余的白色 space,但只留下一个,这会起作用 .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