320 lines
25 KiB
JavaScript
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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
|