• 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

0 głosów
259 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ź 380 wizyt
0 głosów
1 odpowiedź 181 wizyt
0 głosów
0 odpowiedzi 819 wizyt

93,631 zapytań

142,553 odpowiedzi

323,056 komentarzy

63,137 pasjonatów

Advent of Code 2025

Top 15 użytkowników

  1. 2416p. - dia-Chann
  2. 2390p. - DziarnowskiJ
  3. 2317p. - raydeal
  4. 2300p. - Adrian Wieprzkowicz
  5. 2243p. - rucin93
  6. 2242p. - Łukasz Piwowar
  7. 2222p. - CC PL
  8. 2117p. - Łukasz Eckert
  9. 2082p. - Michal Drewniak
  10. 1957p. - Maurycy W
  11. 1885p. - robwarsz
  12. 1811p. - rafalszastok
  13. 1600p. - Rafał Trójniak
  14. 1588p. - Tomasz Bielak
  15. 1377p. - ssynowiec
Szczegóły i pełne wyniki

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

Kursy INF.02 i INF.03
...