我目前正在尝试编写一个抓取工具,它将使用node.js从Facebook帖子内的div中获取所有“p”标签
页面上的每个帖子都位于具有此类的 div 中:.text_exposed_root
有时每个帖子中都有多个“p”标签,因此理想情况下,如果可能的话,我需要获取该 div 中的所有 html 文本。我正在使用 Cheerio 和请求模块,到目前为止我的代码如下:
request(BTTS, function(error, response, body){
if (!error){
var $ = cheerio.load(body),
post = $(".text_exposed_root p").text();
console.log(post);
} else {
console.log("We’ve encountered an error: " + error);
}
})
我尝试过使用 .text .value 和 .html 但它们都只返回空白响应。我猜我需要获取该 div 中的所有“p”标签并可能转换为字符串?
提前致谢。
编辑:
var url = ('https://www.facebook.com/BothTeamsToScore');
request({url:url, headers: headers}, function(error, response, body){
if (!error){
var strippedBody = body.replace(/<!--[\s\S]*?-->/g, "")
console.log(strippedBody);
var $ = cheerio.load(strippedBody),
post = $(".text_exposed_root p").text();
console.log(post);
} else {
console.log("We’ve encountered an error: " + error);
}
})
首先,您需要为您的请求设置一些标头。如果没有它们,Facebook 将通过“不支持的浏览器”页面进行响应。这是你的第一个问题。
var headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.110 Safari/537.36',
'Content-Type' : 'application/x-www-form-urlencoded'
}
var url = BTTS
request({url:url, headers: headers}, function(error, response, body){
if (!error){
var $ = cheerio.load(body.replace(/<!--|-->/g, ''))
console.log($('.text_exposed_root p').text())
} else {
console.log("We’ve encountered an error: " + error);
}
})
另一件事应该注意的是,内容出现在 html 注释中。即
<code class="hidden_elem"><!--
...
<div class="text_exposed_root">
<p>text</p>
Cheerio 不会解析注释节点,因此您很可能需要删除
<!--
和 -->
并将结果加载回 Cheerio 以解析您想要的 html 部分。祝你好运!
有一个库 node-html-parser,您可以使用它来 parse 一个 html 字符串,然后用它来执行类似 DOM 的操作。
在您的情况下,您可以创建一个通过 .text_exposed_root 查询所有 div 的函数,然后提取 innerHtml
文件:html.utiliy.ts
import parse from "node-html-parser";
export class HTMLUtility {
/**
* Function that queries all HTML text by given class name
* @param text actual Html Text as string
* @param className targetted class name
* @returns a list with inner html text found inside class name
*/
public static getAllParagraphsByDivClass(text: string, className: string): string[] {
const root = parse(text);
const htmlDivElement = root.querySelectorAll(`.${className}`);
return htmlDivElement.map((m) => m.innerHTML);
}
}
文件:html.utility.unit.test.ts
import { describe, it } from "mocha";
import { assert } from "chai";
import { HTMLUtility } from "../../../../src/application/helpers/html.utiliy";
describe("HTML Utility", () => {
describe("get all elements inside div", () => {
it("given certain html, will return a list of text inside each div.className", async () => {
// arrange
const post1 = "<p>Lorem ipsum dolor sit amet</p><p>consectetur adipiscing elit.</p>";
const post2 = "<p>Aliquam iaculis ornare massa</p><p>ut porta enim mollis ac.</p>";
const post3 = "<p>Maecenas sodales pretium sollicitudin.</p>";
const htmlText = `
<body>
<div class='text_exposed_root'>${post1}</div>
<div class='text_exposed_root'>${post2}</div>
<div class='text_exposed_root'>${post3}</div>
</body>`;
// act
const paragraphList = HTMLUtility.getAllParagraphsByDivClass(htmlText, "text_exposed_root");
// assert
assert.equal(paragraphList[0], post1);
assert.equal(paragraphList[1], post2);
assert.equal(paragraphList[2], post3);
});
});
});