mono/packages/search/dist-in/lib/html.js
2025-11-25 11:07:35 +01:00

320 lines
25 KiB
JavaScript

import https from 'https';
import axios from "axios";
import * as cheerio from "cheerio";
import * as path from 'path';
import { URL } from 'url';
import * as puppeteer from 'puppeteer';
import { logger } from '../index.js';
export const STATS_SUFFIX = '_stats.json';
export const SESSION_EVENTS_SUFFIX = '_session.json';
export const TRACE_SUFFIX = '_trace.json';
export var scope;
const included_categories = ['devtools.timeline'];
const _url_short = (url) => new URL(url).hostname;
let instance;
const debugRequests = true;
const debugResponses = false;
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
export const extractEmail = (input) => {
// Regular expression to match a typical email format
const emailRegex = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/;
// Use the regex to search for an email in the input string
const match = input.match(emailRegex);
// Return the matched email, or null if none is found
return match ? match[0] : null;
};
export const meta = async (loc, options) => {
if (!loc.website) {
logger.warn(`No website to retrieve meta data : ${loc.title}`);
return;
}
if (loc.meta) {
return;
}
try {
const _meta = await parse(loc.website, null, options) || {};
loc.meta = _meta;
loc.instagram = _meta.instagram;
loc.facebook = _meta.facebook;
loc.youtube = _meta.youtube;
loc.linkedin = _meta.linkedin;
loc.twitter = _meta.twitter;
loc.email = (_meta.allLinks || []).map((l) => extractEmail(l)).filter((e) => e !== null)[0];
return _meta;
}
catch (error) {
logger.error('Error retrieving meta data : ' + loc.website, error.message);
if (error.status)
loc.rejected = error.status === 404 || error.status === 403 || error.status === 999 || error.status === 503;
}
};
export const isValidUrl = (url) => {
try {
new URL(url);
return true;
}
catch (error) {
return false;
}
};
const readMetaTags = ($, name) => {
return $(`meta[name="${name}"]`).attr('content') || $(`meta[property="${name}"]`).attr('content') || null;
};
export const parse = async (url, config, options) => {
if (!/(^http(s?):\/\/[^\s$.?#].[^\s]*)/i.test(url))
return {};
const { data } = await axios(url, {
...config,
httpsAgent: new https.Agent({
rejectUnauthorized: false
}),
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36'
},
timeout: 10000
});
const $ = cheerio.load(data);
const og = {};
const meta = {};
const images = [];
const links = [];
let allLinks = [];
const title = $('title').text();
if (title)
meta.title = title;
const canonical = $('link[rel=canonical]').attr('href');
if (canonical) {
meta.url = canonical;
}
['title', 'description', 'image'].forEach(s => {
const val = readMetaTags($, s);
if (val)
meta[s] = val;
});
['og:title', 'og:description', 'og:image', 'og:url', 'og:site_name', 'og:type'].forEach(s => {
const val = readMetaTags($, s);
if (val)
og[s.split(':')[1]] = val;
});
$('img').each((i, el) => {
let src = $(el).attr('src');
if (src) {
try {
src = new URL(src, url).href;
images.push({ src });
}
catch (e) {
// ignore invalid urls
}
}
});
// Array to store JSON-LD data
const jsonLdArray = [];
// Select all <script> tags with type "application/ld+json"
$('script[type="application/ld+json"]').each((_, element) => {
const jsonLdContent = $(element).html();
if (jsonLdContent) {
try {
// Parse the JSON-LD content and push it to the array
const jsonData = JSON.parse(jsonLdContent);
jsonLdArray.push(jsonData);
}
catch (e) {
logger.error(`Error parsing JSON-LD: ${e.message} @ ${url}`);
}
}
});
$('a').each((index, element) => {
const href = $(element).attr('href');
if (href && isValidUrl(href)) {
if (href.indexOf('contact') !== -1 && !links.includes(href)) {
links.push(href);
}
allLinks.push(href);
}
});
allLinks = [...new Set(allLinks)];
const instagram = allLinks.find(link => link.includes('instagram.com'));
const facebook = allLinks.find(link => link.includes('facebook.com'));
const linkedin = allLinks.find(link => link.includes('linkedin.com'));
const youtube = allLinks.find(link => link.includes('youtube.com'));
const twitter = allLinks.find(link => link.includes('twitter.com'));
const ret = {
meta,
og,
images,
keywords: ($('meta[property="og:keywords"]').attr("content") ||
$('meta[name="keywords"]').attr("content") || "").split(',').map(s => s.trim()).filter(s => s),
links,
allLinks,
instagram,
facebook,
linkedin,
youtube,
twitter,
structured: jsonLdArray
};
return ret;
};
export const getScope = (cliArgs) => {
if (!instance) {
instance = new Scope();
instance.args = cliArgs;
}
return instance;
};
/*
export async function capture_request(where: any[], request: Request) {
debugRequests && logger.debug('Request', { url: request.url(), data: request.postData() });
where.push({ url: request.url(), data: await request.postData(), request: request });
debugRequests && logger.debug('requests', where.map(r => r.url));
}
export async function capture_response(where: any[], response: Response) {
debugResponses && logger.debug('Response', { url: response.url(), data: await response.json() });
where.push(response);
}
*/
export async function capture_responses(scope, page) {
try {
// await page.setRequestInterception(true);
}
catch (e) {
logger.error('error intercepting responses', e);
}
scope.responses = [];
page.on('response', response => {
try {
const isJson = (response.headers()['content-type'] || '').startsWith('application/json;') === true;
const url = response.url();
if (response.status() === 200) {
if (isJson) {
// capture_response(scope.responses, response as any);
}
if (scope.onResponse) {
scope.onResponse(response, scope);
}
}
else {
debugResponses && logger.error(`Error loading ${url} : ${response.status()}`);
}
}
catch (e) {
debugResponses && logger.error('Error parsing response');
}
});
}
export class Scope {
browser;
context;
page;
args;
requests = [];
responses = [];
eventBeacons = [];
mutationBeacons = [];
sessionSuffix = '';
onResponse;
onRequest;
async init() {
this.sessionSuffix = ' - ' + new Date().getTime();
const args = [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-infobars',
'--window-position=0,0',
'--ignore-certifcate-errors',
'--ignore-certifcate-errors-spki-list',
'--user-agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3312.0 Safari/537.36"',
`--user-data-dir=${path.resolve('../chrome')}`
];
this.browser = await puppeteer.launch({
...this.args,
args: args
});
// const context = await this.browser.createIncognitoBrowserContext();
this.page = await this.browser.newPage();
// this.page = await context.newPage();
this.page.on('console', msg => {
// error('Browser error:', msg);
});
this.page.on('error', msg => logger.error('Browser Error:', msg));
this.page.on('pageerror', msg => logger.error('Browser Page Error:', msg));
this.page.on('requestfailed', msg => logger.error('Browser Page Request Error:', msg));
//capture_requests(this, this.page);
//capture_responses(this, this.page);
// this.args.disableRequests !== 'true' && capture_requests(this, this.page);
// this.args.disableResponses !== 'true' && capture_requests(this, this.page);
// capture_responses(this, this.page);
const page2 = this.page;
//page2.setCacheEnabled(false);
/**
await page2._client.on('Security.certificateError', (event: any) => {
page2._client.send('Security.handleCertificateError', {
eventId: event.eventId,
action: 'continue' // ignore error and continue request
})
})
*/
}
}
export const body = async (url) => {
const options = {
headless: false,
url: url
};
let timeout = 8000;
if (!scope) {
try {
scope = await getScope(options);
await scope.init();
}
catch (e) {
debugger;
logger.error("Invalid scope - abort", e);
return;
}
scope.page.on("pageerror", function (err) {
logger.error('page-error!', err);
});
scope.page.on("error", function (err) {
logger.error('brower-error!', err);
});
scope.page.on('console', msg => {
if (msg._type === 'error') {
logger.error('Browser error:', msg);
scope.page.isError = true;
}
});
}
const parse = (resolve) => {
scope.page.content().then((c) => {
if (!c) {
logger.error('error user page ', url);
resolve(null);
return;
}
const $ = cheerio.load(c, {
xmlMode: true
});
const links = [];
$('a').each((index, element) => {
const href = $(element).attr('href');
if (href && href.indexOf('contact') !== -1) {
links.push(href);
}
});
resolve({ html: c, text: $('body').text(), links });
});
};
return new Promise((resolve) => {
scope.page.goto(url, {
timeout: timeout,
waitUntil: 'networkidle0'
}).then((v) => {
parse(resolve);
}).catch((e) => {
logger.error('error loading page', e);
});
});
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHRtbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIvaHRtbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssTUFBTSxPQUFPLENBQUE7QUFFekIsT0FBTyxLQUE2QixNQUFNLE9BQU8sQ0FBQTtBQUNqRCxPQUFPLEtBQUssT0FBTyxNQUFNLFNBQVMsQ0FBQTtBQUNsQyxPQUFPLEtBQUssSUFBSSxNQUFNLE1BQU0sQ0FBQTtBQUM1QixPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sS0FBSyxDQUFBO0FBR3pCLE9BQU8sS0FBTSxTQUFTLE1BQU0sV0FBVyxDQUFBO0FBRXZDLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxhQUFhLENBQUE7QUFHcEMsTUFBTSxDQUFDLE1BQU0sWUFBWSxHQUFHLGFBQWEsQ0FBQTtBQUN6QyxNQUFNLENBQUMsTUFBTSxxQkFBcUIsR0FBRyxlQUFlLENBQUE7QUFDcEQsTUFBTSxDQUFDLE1BQU0sWUFBWSxHQUFHLGFBQWEsQ0FBQTtBQUN6QyxNQUFNLENBQUMsSUFBSSxLQUFZLENBQUE7QUFFdkIsTUFBTSxtQkFBbUIsR0FBRyxDQUFDLG1CQUFtQixDQUFDLENBQUE7QUFDakQsTUFBTSxVQUFVLEdBQUcsQ0FBQyxHQUFXLEVBQUUsRUFBRSxDQUFDLElBQUksR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQTtBQUN6RCxJQUFJLFFBQWUsQ0FBQTtBQUNuQixNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUE7QUFDMUIsTUFBTSxjQUFjLEdBQUcsS0FBSyxDQUFBO0FBRTVCLE9BQU8sQ0FBQyxHQUFHLENBQUMsNEJBQTRCLEdBQUcsR0FBRyxDQUFDO0FBRS9DLE1BQU0sQ0FBQyxNQUFNLFlBQVksR0FBRyxDQUFDLEtBQWEsRUFBaUIsRUFBRTtJQUN6RCxxREFBcUQ7SUFDckQsTUFBTSxVQUFVLEdBQUcsZ0RBQWdELENBQUM7SUFFcEUsMkRBQTJEO0lBQzNELE1BQU0sS0FB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