• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Cheerio i parsowanie html w node

Object Storage Arubacloud
0 głosów
99 wizyt
pytanie zadane 7 września 2020 w JavaScript przez Karol Loczeski Użytkownik (820 p.)
edycja 7 września 2020 przez Karol Loczeski

Witajcie. Przejde do sedna. 

Otrzymuję taki oto html i potrzebuje go obrobić. aby otrzymać pożądany poniżej rezultat. 

    text = `<b>AAA</b>
            <random fb="2000"/> 
            <i>BBB</i> 
            <random fb="9000"/> 
            CCC
            <random fb="2000"/> 
            DDD
            <img src=""/>`

oczekiwany resultat to : 
result = [
       {fb: null, html: '<b>AAA</b>'},
       {fb:'2000',html: '<i>BBB</i>'},
       {fb:'9000',html: 'CCC'},
       {fb:'2000',html: 'DDD'},
       {fb: null, html: ' <img src=""/>'}
     ]

 

Moja rzeźba zwraca tylko stringi i niestety po drodze gubie `AAA` oraz `img`
Proszę o jakaś wskazówkę. 



import { get } from 'lodash';
const $ = cheerio.load(text);
const $random = $('random');

const elements = $random.map((i, item) => {
  const { attribs, next } = item;
  const getFB = attribs.fb.trim();
  const data= get(next, 'data', null);
  const message = { html: data && data.trim() };
  const fb = { fb: Number(getFB) };
return Object.assign({}, fb, message);
}).get();

elements = [ 
       {fb:2000, html: 'BBB'},
       {fb:9000,html: 'CCC'},
       {fb:2000,html: 'DDD'}]

 

1
komentarz 7 września 2020 przez ScriptyChris Mędrzec (190,190 p.)
edycja 7 września 2020 przez ScriptyChris
const data= get(next, 'data', null);

Czym jest ścieżka "data" podana w drugim parametrze? Do zmiennej data przypisana jest zawartość elementu DOM?

https://lodash.com/docs/4.17.15#get

Rozumiem, że next to następny element (rodzeństwo) po item (tak przynajmniej wskazuje dokumentacja Cheerio - tylko, że to funkcja, a ja nie widzę tam wywołania), dlatego nie bierze pod uwagę elementu z treścią "AAA", natomiast na końcu niepotrzebnie wypisuje <img src="">.


Jeśli HTML do sparsowania jest tak prosty i jednolity, jak ten który podałeś, to moim zdaniem nie potrzeba tu używać Cheerio ani tym bardziej lodasha. Wystarczy standardowy parser DOM z obsługą jego API, jak np. jsdom.

komentarz 7 września 2020 przez Karol Loczeski Użytkownik (820 p.)

next  to obiekt wyciągnięty z item, z którego z kolei wyciągam właściwość data.
Chyba już na tym etapie coś pokręciłem bo pomijam `<b>AAA</b>`, który powinien być na samym początku.

console.log($random);

initialize {
  '0': {
    type: 'tag',
    name: 'random',
    attribs: { fb: '2000' },
    children: [],
    next: {
      data: ' \n',
      type: 'text',
      next: [Object],
      prev: [Circular],
      parent: null,
      root: [Object]
    },
    prev: {
      data: '\n',
      type: 'text',
      next: [Circular],
      prev: [Object],
      parent: null,
      root: [Object]
    },
    parent: null,
    root: {
      type: 'root',
      name: 'root',
      attribs: {},
      children: [Array],
      next: null,
      prev: null,
      parent: null
    }
  },
  '1': {
    type: 'tag',
    name: 'random',
    attribs: { fb: '9000' },
    children: [],
    next: {
      data: '\nCCC\n',
      type: 'text',
      next: [Object],
      prev: [Circular],
      parent: null,
      root: [Object]
    },
    prev: {
      data: ' \n',
      type: 'text',
      next: [Circular],
      prev: [Object],
      parent: null,
      root: [Object]
    },
    parent: null,
    root: {
      type: 'root',
      name: 'root',
      attribs: {},
      children: [Array],
      next: null,
      prev: null,
      parent: null
    }
  },
  '2': {
    type: 'tag',
    name: 'random',
    attribs: { fb: '5000' },
    children: [],
    next: {
      data: '\nDDD\n',
      type: 'text',
      next: [Object],
      prev: [Circular],
      parent: null,
      root: [Object]
    },
    prev: {
      data: '\nCCC\n',
      type: 'text',
      next: [Circular],
      prev: [Object],
      parent: null,
      root: [Object]
    },
    parent: null,
    root: {
      type: 'root',
      name: 'root',
      attribs: {},
      children: [Array],
      next: null,
      prev: null,
      parent: null
    }
  }

 

1 odpowiedź

0 głosów
odpowiedź 8 września 2020 przez ScriptyChris Mędrzec (190,190 p.)
edycja 8 września 2020 przez ScriptyChris

Skoro już tak kombinujesz, to zamiast next możesz odwołać się do prev w każdej iteracji, a w ostatniej dodatkowo skorzystać z next - wtedy wyjściowo lista elementów będzie zaczynać się od elementu z "AAA", w ostatniej iteracji dojdzie zawartość z "DDD", który dodasz do listy poza pętlą.

Coś takiego:

import {get} from 'lodash';

const $ = cheerio.load(text);
const $random = $('random');
let lastMessage = {};

const elements = $random.map((i,item)=>{
    const {attribs, next, prev} = item;
    const getFB = attribs.fb.trim();
    const data = get(prev, 'data', null);

    const isLastIteration = i === $random.length - 1;
    if (isLastIteration) {
        const lastIterationData = get(next, 'data', null);

        lastMessage = {
           html: lastIterationData && lastIterationData.trim();
        };
    }

    const message = {
        html: data && data.trim()
    };   

    const fb = {
        fb: Number(getFB)
    };
    return Object.assign({}, fb, message);
}).get();

elements.push(lastMessage);

 

komentarz 14 października 2020 przez Karol Loczeski Użytkownik (820 p.)

To nie zadziała przy bardziej rozbudowanym html ponieważ next i prev również mogą posiadać dodatkowe next i prev itd itd. 

Ulepiłem i działa. Z tagu `random` wyciągamy czas i zastępujemy je specjalnym stringiem, po czym dzielimy splitem nowy html po przez użyty specjalny string.

const $ = cheerio.load(text);
const $random = $('random');
 
const elements = $random.map((i, item) => {
  const { attribs } = item;
  const fb = attribs.fb && parseInt(attribs.fb.trim());
  $(el).replaceWith('--FB--');
  return fb
}).get();


 

Podobne pytania

+1 głos
1 odpowiedź 147 wizyt
0 głosów
1 odpowiedź 112 wizyt
0 głosów
0 odpowiedzi 354 wizyt

92,556 zapytań

141,404 odpowiedzi

319,561 komentarzy

61,942 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...