Files
newsletter_spammer/src/classifier.js
T

110 lines
4.4 KiB
JavaScript

async function classifyNewsletterForm(page) {
const formInfo = await page.evaluate(() => {
const results = {
hasEmailInput: false,
hasNewsletterKeywords: false,
hasSearchInput: false,
hasLoginInput: false,
hasContactForm: false,
hasOnlyEmail: false,
formCount: 0,
emailInputCount: 0,
totalInputCount: 0,
confidence: 0,
reasons: [],
signals: {
positive: [],
negative: []
}
};
const allInputs = document.querySelectorAll('input:not([type="hidden"]):not([type="submit"]):not([type="button"])');
results.totalInputCount = allInputs.length;
const emailInputs = document.querySelectorAll('input[type="email"], input[name*="email" i], input[id*="email" i], input[placeholder*="email" i]');
results.emailInputCount = emailInputs.length;
results.hasEmailInput = emailInputs.length > 0;
if (results.hasEmailInput) {
results.signals.positive.push(`Found ${emailInputs.length} email input(s)`);
}
const pageText = document.body.innerText.toLowerCase();
const titleText = document.title.toLowerCase();
const combinedText = pageText + ' ' + titleText;
const newsletterKeywords = [
'newsletter', 'subscribe', 'signup', 'sign up', 'join our', 'stay updated',
'get updates', 'email updates', 'weekly digest', 'monthly newsletter',
'sign up for updates', 'join the list', 'email list', 'mailing list'
];
for (const keyword of newsletterKeywords) {
if (combinedText.includes(keyword)) {
results.hasNewsletterKeywords = true;
results.signals.positive.push(`Keyword: "${keyword}"`);
}
}
const searchInputs = document.querySelectorAll('input[type="search"], input[name*="search" i], input[id*="search" i], input[placeholder*="search" i]');
results.hasSearchInput = searchInputs.length > 0;
if (results.hasSearchInput) {
results.signals.negative.push('Search input detected');
results.reasons.push('Search input detected');
}
const passwordInputs = document.querySelectorAll('input[type="password"]');
const usernameInputs = document.querySelectorAll('input[name*="username" i], input[name*="login" i], input[id*="username" i]');
results.hasLoginInput = passwordInputs.length > 0 || usernameInputs.length > 0;
if (results.hasLoginInput) {
results.signals.negative.push('Login/password fields detected');
results.reasons.push('Login/password fields detected');
}
const contactKeywords = ['contact us', 'get in touch', 'send message', 'inquiry'];
for (const keyword of contactKeywords) {
if (combinedText.includes(keyword)) {
results.hasContactForm = true;
results.signals.negative.push(`Contact form keyword: "${keyword}"`);
break;
}
}
const nonEmailInputs = Array.from(allInputs).filter(input => {
const type = input.type?.toLowerCase();
const name = input.name?.toLowerCase() || '';
return type !== 'email' && !name.includes('email');
});
results.hasOnlyEmail = results.hasEmailInput && nonEmailInputs.length === 0;
if (results.hasOnlyEmail) {
results.signals.positive.push('Only email field (no other inputs)');
}
let score = 0;
if (results.hasEmailInput) score += 40;
if (results.hasNewsletterKeywords) score += 35;
if (results.hasOnlyEmail) score += 15;
if (results.totalInputCount <= 3) score += 10;
if (!results.hasSearchInput) score += 10;
if (!results.hasLoginInput) score += 15;
if (!results.hasContactForm) score += 5;
if (results.hasSearchInput) score -= 30;
if (results.hasLoginInput) score -= 50;
if (results.hasContactForm && !results.hasNewsletterKeywords) score -= 20;
results.confidence = Math.max(0, Math.min(100, score));
results.isNewsletter = results.confidence >= 55;
return results;
});
return formInfo;
}
module.exports = {
classifyNewsletterForm
};