Как очистить 2 дива, которые находятся на одном уровне с Cheerio

Я пытаюсь очистить веб-контент из двух разных разделов, которые находятся на одном уровне. Я использую NodeJS, Axios, Cheerio и Express.

По сути, я пытаюсь собрать изображение и связанную с ним информацию, но они размещены в разных разделах, находящихся на одном уровне. Использование «основного» в моем случае не работает.

<div class = "main">
    <div class = "one">
        // image
    </div>
    <div class = "two">
        // info
    </div>
</div>

Ниже приведен мой код для получения данных с веб-сайта:

var leafletList = $('.store-flyer__info', html).each(function() {
    let leaflet = {
        title: $(this).find('h3').text(),
        image: $(this).find('source').attr('srcset'),
        link: $(this).find('a').attr('href'),
        validDate: $(this).find('small').text().slice(3,-1)
    }

    leaflets.push(leaflet)
})

Ниже приведен HTML-код веб-сайта:

В моем коде прямо сейчас он, очевидно, получает только заголовок, ссылку и validDate. Но кто-нибудь знает, как я могу получить srcset из другого div? Я также пробовал следующий метод, но он не работает:

var leafletList = $('.store-flyers', html).each(function() {
    let leaflet = {
        title: $(this).find('.store-flyer__info h3').text(),
        image: $(this).find('.store-flyer__front source').attr('srcset'),
        link: $(this).find('.store-flyer__info a').attr('href'),
        validDate: $(this).find('.store-flyer__info small').text().slice(3,-1)
    }

    leaflets.push(leaflet)
})

🤔 А знаете ли вы, что...
Node.js позволяет создавать высокоэффективные приложения для обработки потоковой передачи данных.


63
2

Ответы:

С помощью Cheerio вы можете получить доступ к таким свойствам узла, как:

parentNode
previousSibling
nextSibling
nodeValue
firstChild
childNodes
lastChild

<div class = "main">
    <div class = "one">
        // image
    </div>
    <div class = "two">
        // info
    </div>
</div>

.main.firstChild — это .one

.one.nextSibling — это .two

.main.lastChild — это .two

.two.previousSibling is .one


Решено

Есть много способов получить результат на основе показанного фрагмента HTML, с оговоркой, что инструменты разработчика могут вводить в заблуждение. Он показывает элементы, созданные после загрузки страницы с помощью JS, которых у вас не будет, если вы запрашиваете только необработанный HTML-код страницы.

Имея это в виду, вот несколько вариантов:

const cheerio = require("cheerio"); // ^1.0.0-rc.12

const html = `
<div class = "store-flyer">
  <picture>
    <source srcset = "foo.jpeg" type = "image/webp">
    <source srcset = "bar.jpeg" type = "image/jpeg">
  </picture>
</div>
<div class = "store-flyer">
  <picture>
    <source srcset = "quux.jpeg" type = "image/webp">
    <source srcset = "garply.jpeg" type = "image/jpeg">
  </picture>
</div>
`;
const $ = cheerio.load(html);
const result = [...$(".store-flyer")].map(e => ({
  // select using `.first()` and `.last()` Cheerio methods:
  firstImage: $(e).find("source").first().attr("srcset"),
  secondImage: $(e).find("source").last().attr("srcset"),

  // select using CSS attribute selectors:
  firstImageByType: $(e).find('source[type = "image/webp"]').attr("srcset"),
  secondImageByType: $(e).find('source[type = "image/jpeg"]').attr("srcset"),

  // select as an array of all <source> elements:
  allImages: [...$(e).find("source")].map(e => $(e).attr("srcset")),
}));
console.info(result);

Выход:

[
  {
    firstImage: 'foo.jpeg',
    secondImage: 'bar.jpeg',
    firstImageByType: 'foo.jpeg',
    secondImageByType: 'bar.jpeg',
    allImages: [ 'foo.jpeg', 'bar.jpeg' ]
  },
  {
    firstImage: 'quux.jpeg',
    secondImage: 'garply.jpeg',
    firstImageByType: 'quux.jpeg',
    secondImageByType: 'garply.jpeg',
    allImages: [ 'quux.jpeg', 'garply.jpeg' ]
  }
]

Добавление .store-flyer__front к вашим селекторам source может быть хорошей идеей, если вам нужно устранить неоднозначность.