Проблемма с cheerio и масивом
У меня есть функция которая в зависимости от параметров парсит или названия или цены или url . Последнее и первое отлично работает . Цены вообще не хочет парсить хотя вроде всё норм сделано . Вот код:
const puppeteer = require('puppeteer');
const cheerio = require('cheerio');
async function getPageContent(url){
try {
const browser = await puppeteer.launch()
const page = await browser.newPage()
await page.goto(url)
const content = await page.content()
await browser.close();
//console.log(content);
return content;
}catch (error){
throw error
}
}
async function getElements($, sel, options){
try {
let elements = [];
let element
//проходимся по всем элементам масива по селектору(sel)
$(sel).each((idx, elem) =>{
if(options.isParent){
element = $(elem).parent()
}
else {
element = $(elem)
}
if(options.elType === 'title'){
let title = element.text()
let obj = {
id: idx,
title: title,
}
elements.push(obj);
}
if(options.elType === 'price'){
let price = element.text();
//Это на случай пробелов и лишних символов в строчке
price = price.split(" ").join('')
price = price.split("\n").join('')
if(price === '-' || price === ''){
price = 'Нет в продаже'
}
//Если валюта рубли то добовляем "руб"
if(options.valute === 'руб'){
if(price !== 'Нет в продаже'){
price = `${price} руб`
let obj = {
id: idx,
price: price,
}
elements.push(obj);
}else{
let obj = {
id: idx,
price: price,
}
elements.push(obj);
}
}
}
if(options.elType === 'url'){
let obj;
let url = element.attr('href')
if(!url.startsWith(options.siteURL)){
obj = {
id: idx,
url: `${options.siteURL}${url}`,
}
}
else{
obj = {
id: idx,
url: url,
}
}
elements.push(obj);
}
})
return elements;
//console.log(elements)
}catch (error){
console.log(error);
}
}
async function getBooks(name,url,opts){
try{
const content = await getPageContent(`${url}${name}`);
const $ = cheerio.load(content);
let books = '';
let titles = await getElements($, opts.titleOpts.sel, opts.titleOpts)
let prices = await getElements($, opts.priceOpts.sel, opts.priceOpts)
for(let i = 0; i < titles.length - 1; i++){
books = `${books}|${titles[i].id + 1}| ${titles[i].title} - ${prices[i].price} \n`
}
console.log(books)
return(books)
}catch (err){
console.error(err)
}
}
async function test(name) {
try {
const url = "https://librarius.md/ru/search?search="
const librOpts = {
titleOpts: {
elType: 'title',
sel: '.card-title'
},
priceOpts: {
elType: 'price',
sel: '.card-price',
valute: 'лей'
}
}
let books = await getBooks(name, url, librOpts)
} catch (err) {
console.error(err)
}
}
test('Ведьмак')
Прекол в том что в консоль выводится ошибка о том что prices[i].price undefined . Я проверял код и по идее такого не может быть . Помогите пожалуйста я не могу найти свою ошибку
Ответы (1 шт):
Автор решения: nörbörnën
→ Ссылка
Ты получаешь пустой список цен из-за того, что "цену" в "список" ты добавляешь только если валюта - рубль.
Вот в этот условный оператор ты можешь войти только если options.valute === 'руб', а в аргументах передаётся лей:
if (options.valute === 'руб') {
if (price !== 'Нет в продаже') {
...
elements.push(obj);
} else {
...
elements.push(obj);
}
}
priceOpts: {
elType: 'price',
sel: '.card-price',
valute: 'лей'
}
Должно быть примерно так:
if (options.elType === 'price') {
let price = element.text()?.replace(/\s/g, '');
if (price === '-' || price === '') {
price = 'Нет в продаже';
} else if (options.valute === 'руб') {
price = `${price} руб`;
}
elements.push({ id: idx, price });
}