Как очистить «сырые» текстовые узлы между именованными элементами с помощью Cheerio - PullRequest
0 голосов
/ 21 апреля 2019

Cheerio не любит html без правильных тегов (кто на самом деле?).Я пытаюсь очистить некоторые меню, и контент, который я хочу, находится между элементами в html.Есть ли способ разобрать каждый из них и сохранить их как куски, используя cheerio?Меню представляет собой 5-дневное меню с различными курсами ниже каждого дня.Элемент (дни) находится на том же уровне (братья и сестры), что и пункты меню.

Вот сложная часть: пункты меню не имеют никаких атрибутов.Это «необработанный» текстовый узел.

Я не могу изменить html.

Вот структура html, обратите внимание, что необработанные текстовые узлы являются «родственными» для «заголовков».

<div class="meny" style="clear:left;line-height:1.6em;padding-bottom:2em;">
    <strong>Måndag</strong>
    <br>Klassisk wallenbergare på kalvfärs serveras med gräddsås, lingonsylt, och potatismos
    <br>Dragonbrässerad fiskfilé serveras med basilika och ruccolacrème samt kokt potatis
    <br>Pasta med strimlad ryggbiff, champinjoner och lök i krämig grönpepparsås
    <br>Pasta vegetale med rostad paprika, lök och purjolök i krämig örtsås
    <br>Grillad högrevsburgare serveras med ost, bacon, briochebröd och country fries
    <br>
    <br><strong>Tisdag</strong>
    <br>Stekt fläsk med löksås, bruna bönor eller raggmunk och lingon
    <br>Thailändsk biffgryta med citrongräs, kokosgrädde, limeblad, wokgrönsaker och rödcurry
    <br>Hollandaisebakad torskfilé på purjolöksbädd serveras med vitvinssås och kokt potatis
    <br>Pasta penne med bacon, ädelost, champinjoner, blomkål och grädde
    <br>Vegetarisk Thaigryta serveras med jasminris
    <br>Grillad högrevsburgare serveras med ost, bacon, briochebröd och country fries
    <br>
    <br><strong>Onsdag</strong>
    <br>Kycklingschnitzel serveras med barbequesås och rostad kulpotatis
    <br>Honung och enbärsbakad laxfilé serveras med citruscrème och örtslungad potatis
    <br>Pasta med strimlad kycklingfilé i rosmarin och citronsås
    <br>Karibisk falafelrulle med salsa och vitlöksdressing
    <br>Grillad högrevsburgare serveras med ost, bacon, briochebröd och country fries
    <br>
    <br><strong>Torsdag</strong>
    <br>Grillad karréskiva serveras med bearnaisesås och klyftpotatis
    <br>Stekt dubbelpanerad fiskfilé serveras med dill och rödlöksröra
    <br>Pasta med strimlad fläskfilé, paprika och lök i krämig gorgonzolasås
    <br>Grillad högrevsburgare serveras med ost, bacon, briochebröd och country fries
    <br>
    <br><strong>Fredag</strong>
    <br>LÅNGFREDAG STÄNGT</div>

желаемый вывод json, "день" для i18n ...

weekMenu = {
            name: "menuname",


            weekDayMenus: {
                monday: {
                    day: "",
                    dayMenu: "",
                },
                tuesday: {
                    day: "",
                    dayMenu: "",
                },
                wednesday: {
                    day: "",
                    dayMenu: "",
                },
                thursday: {
                    day: "",
                    dayMenu: "",
                },
                friday: {
                    day: "",
                    dayMenu: "",
                },
            }
        };

Вот то, что я пробовал до сих пор, само собой разумеется, это не работает, так как тольковыводит заголовки.Он не включает дочерние элементы текстового узла с content (), так как они являются братьями и сестрами, а не детьми.

cheeriojs

   var a = $('div.meny')
                    .clone()
                    .remove().eq(0) //remove second menu div    
                    .find('strong').eq(0) //point to first 'day'
                    .siblings() //select the other days
                    .remove() //remove the other days
                    .end() //move pointer back to the start


                    .contents() //get the text nodes associated with the selected 'header'
                    .filter(function (idx, elem) {
                        console.log(elem.data)
                        return elem.type === 'text';
                    })
                    .end()
                    .text()

Ответы [ 2 ]

0 голосов
/ 23 апреля 2019

Решение:

///function
let menu = $('div.meny').slice(0, 1).children('strong').map((i, strong) => {

                    var nodez = getNextSiblings.getAll($(strong)[0])

                    const dayMenuToReturn = []
                    for (var i = 0; i < nodez.length; i++) {

                        if (nodez[i].type === "text") {
                            dayMenuToReturn.push(nodez[i].data)
                        }

                        if (nodez[i].name === "strong") {
                            break
                        }
                    }

                    return {
                        day: $(strong).text(),
                        dayMenu: dayMenuToReturn
                    }
                }).get()
///GetNextSiblings.js
exports.getAll = function (el) {
    var siblings = [];
    while (el = el.nextSibling) {
        siblings.push(el)
    }
    return siblings;
}

Выход:

[
    {
        "day": "Måndag",
        "dayMenu": [
            "ANNANDAG PÅSKSTÄNGT!!"
        ]
    },
    {
        "day": "Tisdag",
        "dayMenu": [
            "Köttfärslimpa serveras med gräddsås, potatismos, lingonsylt och pressgurka",
            "Soltorkad tomatbakad sejfilé serveras med basilikasås",
            "Pasta chicken thai med kycklingfilé och grönsaker i krämig thaisås",
            "Pasta Pesto vegetale med zucchini, röd paprika och rödlök i krämig pestosås",
            "Kebabrulle serveras med fefferoni, sriracha och vitlöksdressing"
        ]
    },
    {
        "day": "Onsdag",
        "dayMenu": [
            "Italiensk kalvfärsbiff serveras med röd pestosås och basilikarostad kulpotatis",
            "Sprödbakad torskfilé serveras med skirat smör och gröna ärtor",
            "Pasta carbonara serveras med äggula, riven grand padano",
            "Indisk lins och böngryta serveras med basmatiris och mynta yoghurt",
            "Kebabrulle serveras med fefferoni, sriracha och vitlöksdressing"
        ]
    },
    {
        "day": "Torsdag",
        "dayMenu": [
            "Säsongens sista Ärtsoppa eller krämig hummersoppa serveras med pannkakor, sylt och grädde",
            "Kreolsk kycklinggryta serveras med cajunkokt ris och chiliaioli",
            "Pocherad torskfilé serveras med purjolöksås och handskalade räkor",
            "Pasta penne med strimlad kycklingfilé och grönsaker i mild gorgonzolasås",
            "Vegetarisk ärtsoppa serveras med pannkakor, sylt och grädde",
            "Kebabrulle serveras med fefferoni, sriracha och vitlöksdressing"
        ]
    },
    {
        "day": "Fredag",
        "dayMenu": [
            "Grilltallrik med karréskiva, choritzo, drumstick, bearnaisesås, barbequesås och klyftpotatis",
            "Stekt dubbelpanerad fiskfilé serveras med remouladsås och pommes frites",
            "Pasta med räkor, kräftstjärtar, fänkål och blekselleri i krämig purjolöksås",
            "Ris och quornfärsfylld paprika serveras med yoghurt och tomatsås",
            "Kebabrulle serveras med fefferoni, sriracha och vitlöksdressing"
        ]
    }
]

Спасибо за помощь, карта это дерьмо ☻

0 голосов
/ 22 апреля 2019

Вот что я бы сделал:

let menu = $('strong').map((i, strong) => {
  return {
    name: $(strong).text(),
    weekDayMenus: {
      monday: {
        day: "",
        dayMenu: $(strong).next()[0].nextSibling.data.trim(),
      },
      tuesday: {
        day: "",
        dayMenu: $(strong).next().next()[0].nextSibling.data.trim(),
      },
    }
  }
}).get()

Итак, объяснение состоит в том, что next() дает узел приветствия, поэтому вы хотите next()[0], который является узлом javascript, и у него есть nextSibling (который может быть текстовым узлом)

Похоже, у последнего нет полного меню, поэтому вам нужно будет добавить обработку исключений.

...