StarrySkyWorld's picture
Initial commit
494c89b
"""
Console Collector - перехват console.log/error/warn
"""
from typing import Dict, List
from .base import BaseCollector
class ConsoleCollector(BaseCollector):
"""
Перехватывает console.log, console.error, console.warn.
Полезно для:
- Отладки JavaScript ошибок
- Понимания что происходит в AWS скриптах
- Обнаружения проблем с fingerprint
"""
name = "console"
def __init__(self, session):
super().__init__(session)
self._logs = []
def inject(self):
"""Инжектит перехватчик console"""
if not self.page:
return
interceptor_js = '''
(function() {
if (window.__consoleInterceptorInstalled) return;
window.__consoleInterceptorInstalled = true;
window.__consoleLogs = [];
const maxLogs = 500;
function captureLog(type, args) {
const entry = {
timestamp: Date.now(),
type: type,
message: args.map(arg => {
try {
if (typeof arg === 'object') {
return JSON.stringify(arg).substring(0, 1000);
}
return String(arg).substring(0, 1000);
} catch(e) {
return '[Unable to stringify]';
}
}).join(' ')
};
window.__consoleLogs.push(entry);
// Ограничиваем размер
if (window.__consoleLogs.length > maxLogs) {
window.__consoleLogs = window.__consoleLogs.slice(-maxLogs);
}
}
const origLog = console.log;
const origError = console.error;
const origWarn = console.warn;
const origInfo = console.info;
const origDebug = console.debug;
console.log = function(...args) {
captureLog('log', args);
return origLog.apply(console, args);
};
console.error = function(...args) {
captureLog('error', args);
return origError.apply(console, args);
};
console.warn = function(...args) {
captureLog('warn', args);
return origWarn.apply(console, args);
};
console.info = function(...args) {
captureLog('info', args);
return origInfo.apply(console, args);
};
console.debug = function(...args) {
captureLog('debug', args);
return origDebug.apply(console, args);
};
// Перехватываем глобальные ошибки
window.addEventListener('error', function(event) {
captureLog('uncaught_error', [
event.message,
'at', event.filename,
'line', event.lineno,
'col', event.colno
]);
});
window.addEventListener('unhandledrejection', function(event) {
captureLog('unhandled_rejection', [
event.reason ? (event.reason.message || String(event.reason)) : 'Unknown rejection'
]);
});
console.log('[ConsoleCollector] Interceptor installed');
})();
'''
try:
self.page.run_js(interceptor_js)
self.page.run_cdp('Page.addScriptToEvaluateOnNewDocument', source=interceptor_js)
self.log("Console interceptor injected")
except Exception as e:
self.log(f"Injection failed: {e}")
def collect(self) -> List[Dict]:
"""Собирает перехваченные логи"""
if not self.page:
return []
try:
logs = self.page.run_js('''
const logs = window.__consoleLogs || [];
window.__consoleLogs = [];
return logs;
''') or []
# Фильтруем и логируем важные
for log in logs:
log_type = log.get('type', '')
message = log.get('message', '')
# Логируем ошибки и предупреждения
if log_type in ('error', 'uncaught_error', 'unhandled_rejection'):
self.log(f"ERROR: {message[:100]}...")
elif log_type == 'warn' and any(x in message.lower() for x in ['fingerprint', 'fwcim', 'automation']):
self.log(f"WARN: {message[:100]}...")
self._logs.append(log)
return logs
except:
return []
def on_step_end(self, step):
"""Добавляем логи к шагу"""
step.console_logs = self._logs.copy()
self._logs = []
def get_errors(self) -> List[Dict]:
"""Возвращает только ошибки"""
return [log for log in self._logs if log.get('type') in ('error', 'uncaught_error', 'unhandled_rejection')]