Я пытаюсь очистить веб-сайт, используя Puppeteer и Cheerio. Я получил HTML-код страницы, которую хочу очистить с помощью puppeteer. Я загрузил этот HTML-код в Cheerio.
async function run() {
const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
const html = await get_to_page_with_required_source_code(page);
const $ = cheerio.load(html);
await browser.close();
}
run();
Сейчас я хочу удалить из HTML все элементы, не содержащие текста. Ниже приведен пример.
<div class = "abc">
<img src = "..." />
</div>
<div class = "def">
<div class = "jkl">
<span class = "ghi">This is a text</span>
</div>
<div class = "mno">This is another text</div>
</div>
Вывод приведенного выше HTML должен быть:
<span class = "ghi">This is a text</span>
<div class = "mno">This is another text</div>
поскольку это единственные два элемента, содержащие текст.
Как я могу это сделать?
вам необходимо уточнить, как обрабатывать вложенные и встроенные элементы.
Если можете, попробуйте реализовать это в JavaScript:
if (element.innerText.trim() != "") {
// element has content
} else {
// element is empty
}
Это очень-очень широкий ответ.
Это не работает, потому что практически все элементы имеют .innerHTML
, включая любые закрывающие теги других элементов, в которых есть HTML, включая все тело. Все, что ему соответствует, это что-то вроде <p></p>
, но даже если бы это было то, чего хотел ОП, все равно недостаточно кода, чтобы это произошло.
Во-первых, вообще не совмещайте Puppeteer и Cheerio. Либо сайт является динамическим, и в этом случае используйте Puppeteer и работайте напрямую с действующим DOM (используйте jQuery, если вам нравится синтаксис Cheerio), либо, если сайт статический, используйте только fetch и Cheerio и пропустите медлительность Puppeteer.
Вот один из способов сделать это с помощью Cheerio (вы можете добавить fetch для запроса данных, если это статический сайт):
const cheerio = require("cheerio"); // ^1.0.0-rc.12
const html = `
<div class = "abc">
<img src = "..." />
</div>
<div class = "def">
<div class = "jkl">
<span class = "ghi">This is a text</span>
</div>
<div class = "mno">This is another text</div>
</div>`;
const $ = cheerio.load(html);
const textEls = [...$("*")]
.filter(e => $(e).children().length === 0 && $(e).text().trim())
.map(e => $.html($(e)));
console.info(textEls);
Вот как это сделать с помощью Puppeteer:
const puppeteer = require("puppeteer"); // ^22.10.0
const html = `<Same as above>`;
let browser;
(async () => {
browser = await puppeteer.launch();
const [page] = await browser.pages();
await page.setContent(html, {waitUntil: "domcontentloaded"});
const textEls = await page.$$eval("*", els =>
els
.filter(e => e.children.length === 0 && e.textContent.trim())
.map(e => e.outerHTML)
);
console.info(textEls);
})()
.catch(err => console.error(err))
.finally(() => browser?.close());
Вывод в обоих случаях одинаков (вы можете добавить .join("\n")
, если хотите, чтобы вывод был строкой именно такой, как вы ее опубликовали):
[
'<span class = "ghi">This is a text</span>',
'<div class = "mno">This is another text</div>'
]
Имейте в виду: это немного странное желание, поэтому может быть, есть лучший способ достичь того, чего вы действительно пытаетесь достичь.
Пожалуйста, покажите нам, что вы пробовали