2024-12-17 12:38:28 +01:00
|
|
|
import * as cheerio from 'cheerio';
|
|
|
|
|
|
|
|
|
|
let $ = null;
|
|
|
|
|
|
|
|
|
|
export function loadParser(text) {
|
2025-01-07 12:25:19 +01:00
|
|
|
$ = cheerio.load(text);
|
2024-12-17 12:38:28 +01:00
|
|
|
}
|
|
|
|
|
|
2025-01-07 12:25:19 +01:00
|
|
|
export function parse(crawlContainer, crawlFields, text, url) {
|
|
|
|
|
if (!text) {
|
|
|
|
|
console.warn('Cannot parse, text was empty for url ', url);
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!crawlContainer || !crawlFields) {
|
|
|
|
|
console.warn('Cannot parse, selector was empty for url ', url);
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const result = [];
|
|
|
|
|
|
|
|
|
|
if ($(crawlContainer).length === 0) {
|
|
|
|
|
console.error('No elements in crawl container found for url ', url);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$(crawlContainer).each((_, element) => {
|
|
|
|
|
const container = $(element);
|
|
|
|
|
const parsedObject = {};
|
|
|
|
|
|
|
|
|
|
// Parse fields based on crawlFields
|
|
|
|
|
for (const [key, fieldSelector] of Object.entries(crawlFields)) {
|
|
|
|
|
let value;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const selector = fieldSelector.includes('|')
|
|
|
|
|
? fieldSelector.substring(0, fieldSelector.indexOf('|')).trim()
|
|
|
|
|
: fieldSelector;
|
|
|
|
|
|
|
|
|
|
if (selector.includes('@')) {
|
|
|
|
|
const [sel, attr] = selector.split('@');
|
|
|
|
|
if (sel.length === 0) {
|
|
|
|
|
value = container.attr(attr.trim());
|
|
|
|
|
} else {
|
|
|
|
|
value = container.find(sel.trim()).attr(attr.trim());
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
value = container.find(selector.trim()).text();
|
|
|
|
|
}
|
2024-12-17 12:38:28 +01:00
|
|
|
|
2025-01-07 12:25:19 +01:00
|
|
|
// Apply modifiers if specified
|
|
|
|
|
if (fieldSelector.includes('|')) {
|
|
|
|
|
/* eslint-disable no-unused-vars */
|
|
|
|
|
const [_, ...modifiers] = fieldSelector.split('|').map((s) => s.trim());
|
|
|
|
|
/* eslint-disable no-unused-vars */
|
|
|
|
|
value = applyModifiers(value, modifiers);
|
|
|
|
|
}
|
2024-12-17 12:38:28 +01:00
|
|
|
|
2025-01-07 12:25:19 +01:00
|
|
|
parsedObject[key] = value || null;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(`Error parsing field '${key}' with selector '${fieldSelector}':`, error);
|
|
|
|
|
parsedObject[key] = null;
|
|
|
|
|
}
|
2024-12-17 12:38:28 +01:00
|
|
|
}
|
|
|
|
|
|
2025-01-07 12:25:19 +01:00
|
|
|
if (parsedObject.id != null) {
|
|
|
|
|
result.push(parsedObject);
|
|
|
|
|
} else {
|
|
|
|
|
console.warn('ID not found. Not relaying object.');
|
|
|
|
|
}
|
|
|
|
|
});
|
2024-12-17 12:38:28 +01:00
|
|
|
|
2025-01-07 12:25:19 +01:00
|
|
|
return result;
|
2024-12-17 12:38:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Helper function to apply modifiers
|
|
|
|
|
function applyModifiers(value, modifiers) {
|
2025-01-07 12:25:19 +01:00
|
|
|
if (!value) return value;
|
|
|
|
|
|
|
|
|
|
modifiers.forEach((modifier) => {
|
|
|
|
|
switch (modifier) {
|
|
|
|
|
case 'int':
|
|
|
|
|
value = parseInt(value, 10);
|
|
|
|
|
break;
|
|
|
|
|
case 'trim':
|
|
|
|
|
value = value.replace(/\s+/g, ' ').trim();
|
|
|
|
|
break;
|
|
|
|
|
case 'removeNewline':
|
|
|
|
|
value = value.replace(/\n/g, ' ');
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
console.warn(`Unknown modifier: ${modifier}`);
|
|
|
|
|
}
|
|
|
|
|
});
|
2024-12-17 12:38:28 +01:00
|
|
|
|
2025-01-07 12:25:19 +01:00
|
|
|
return value;
|
2024-12-17 12:38:28 +01:00
|
|
|
}
|