如何使用Cheerio在命名元素之间抓取“原始”文本节点

问题描述 投票:0回答:2

Cheerio不喜欢没有正确标签的html(谁呢,真的吗?)。我正在尝试刮一些菜单,我想要的内容是在html中的元素之间。有没有办法解析每个这些并使用cheerio将它们保存为块?菜单是5天的菜单,每天下面有不同的课程。元素(天)与菜单项处于同一级别(兄弟)。

这是棘手的部分:菜单项没有任何属性。它是一个“原始”文本节点。

我无法更改html。

这是html结构,请注意原始文本节点是'headers'的兄弟节点。

<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输出,“day”是针对i18n ...

weekMenu = {
            name: "menuname",


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

这是我到目前为止所尝试的,不用说,它不起作用,因为它只输出标题。它不包含具有contents()的文本节点子节点,因为它们是兄弟节点而不是子节点。

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()
node.js web-scraping cheerio textnode
2个回答
0
投票

这就是我要做的事情:

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()给了一个cheerio节点,所以你想要next()[0]这是一个javascript节点,那些有nextSibling(可以是文本节点)

看起来最后一个没有完整菜单,因此您需要添加异常处理。


0
投票

解决方案:

///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"
        ]
    }
]

谢谢你帮忙,地图就是狗屎

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.