Получение всего текстового содержимого из строки HTML в NodeJS - PullRequest
1 голос
/ 03 марта 2020

Мне нужно получить только текстовое содержимое из строки HTML с пробелом или разрывом строки, разделяющей текстовое содержимое различных элементов.

Например, строка HTML может быть:

<ul>
  <li>First</li>
  <li>Second</li>
</ul>

Что я хочу:

First Second

или

First
Second

Я пытался получить текстовое содержимое, сначала обернув всю строку внутри div а затем получить textContent с использованием сторонних библиотек. Но между текстовым содержимым различных элементов, которые мне особенно нужны, нет пробелов или разрывов строк (т.е. я получаю FirstSecond, что не то, что я хочу).

Единственное решение, о котором я сейчас думаю, это создать дерево DOM, а затем применить рекурсию, чтобы получить узлы, содержащие текст, а затем добавить текст этого элемента в строку с пробелами. Есть ли более чистое, аккуратное и простое решение, чем это?

Ответы [ 3 ]

2 голосов
/ 07 апреля 2020

Используя DOM, вы можете использовать document.Node.textContent. Однако NodeJs не имеет textContent (поскольку он не имеет собственного доступа к DOM), поэтому вам следует использовать внешние пакеты. Вы можете установить request и cheerio, используя npm. cheerio, предложенный Джоном Черчем , - это, пожалуй, самый простой инструмент для чистки веб-страниц (есть и более сложные, такие как jsdom). С силой cheerio и request в ваших руках, вы мог написать

const request = require("request");
const cheerio = require("cheerio");
const fs = require("fs");

//taken from https://stackoverflow.com/a/19709846/10713877
function is_absolute(url)
{
    var r = new RegExp('^(?:[a-z]+:)?//', 'i');
    return r.test(url);
}

function is_local(url)
{
    var r = new RegExp('^(?:file:)?//', 'i');
    return (r.test(url) || !is_absolute(url));
}

function send_request(URL)
    {
        if(is_local(URL))
        {
            if(URL.slice(0,7)==="file://")
                url_tmp = URL.slice(7,URL.length);
            else
                url_tmp = URL;

           //taken from https://stackoverflow.com/a/20665078/10713877
           const $ = cheerio.load(fs.readFileSync(url_tmp));
           //Do something
           console.log($.text())
        }
        else
        {
            var options = {
                url: URL,
                headers: {
                  'User-Agent': 'Your-User-Agent'
                }
              };

            request(options, function(error, response, html) {
                //no error
                if(!error && response.statusCode == 200)
                {
                    console.log("Success");

                    const $ = cheerio.load(html);


                    return Promise.resolve().then(()=> {
                        //Do something
                        console.log($.text())
                    });
                }
                else
                {
                    console.log(`Failure: ${error}`);
                }
            });
        }
    }

Позвольте мне объяснить код. Вы передаете URL функции send_request. Он проверяет, является ли строка URL-адреса путем к вашему локальному файлу (относительный путь или путь, начинающийся с file://). Если это локальный файл, он продолжает использовать модуль cheerio, в противном случае он должен отправить запрос на веб-сайт, используя модуль request, а затем использовать модуль cheerio. Регулярные выражения используются в is_absolute и is_local. Вы получаете текст, используя text() метод, предоставленный cheerio. Под комментариями //Do something вы можете делать с текстом все, что захотите. Существуют веб-сайты, которые сообщают вам 'Your-User-Agent', скопируйте и вставьте в это поле свой пользовательский агент.

Ниже будут работать строки

//your local file
send_request("/absolute/path/to/your/local/index.html"); 
send_request("/relative/path/to/your/local/index.html"); 
send_request("file:///absolute/path/to/your/local/index.html"); 
//website
send_request("https://stackoverflow.com/"); 

РЕДАКТИРОВАТЬ: Я в системе linux.

2 голосов
/ 07 апреля 2020

Хорошо, вы можете попробовать этот пример, Это может помочь вам

Я использовал JSDom модуль

https://www.npmjs.com/package/jsdom

const jsdom = require("jsdom");
const { JSDOM } = jsdom;
const dom = new JSDOM(`<!DOCTYPE html><p>Hello world</p>`);
console.log(dom.window.document.querySelector("p").textContent); 

Кстати, помог мне enter image description here

Этот код может помочь, я думаю:)

1 голос
/ 03 марта 2020

Вы можете попробовать избавиться от тегов html с помощью регулярных выражений, для вашего примера попробуйте следующее:

let str = `<ul>
<li>First</li>
<li>Second</li>
</ul>`

console.log(str)

let regex = '<\/?!?(li|ul)[^>]*>'

var re = new RegExp(regex, 'g');

str = str.replace(re, '');
console.log(str)
...