correção do uso de headers dos useragents

This commit is contained in:
Renan Bernordi 2024-11-26 13:46:09 -03:00
parent 97a7bb36de
commit 10a8aa43ec

View file

@ -1,4 +1,5 @@
<?php
/**
* Classe responsável pela análise e processamento de URLs
*
@ -13,7 +14,8 @@
require_once 'Rules.php';
require_once 'Cache.php';
class URLAnalyzer {
class URLAnalyzer
{
/**
* @var array Lista de User Agents disponíveis para requisições
*/
@ -43,7 +45,8 @@ class URLAnalyzer {
* Construtor da classe
* Inicializa as dependências necessárias
*/
public function __construct() {
public function __construct()
{
$this->userAgents = USER_AGENTS;
$this->maxAttempts = MAX_ATTEMPTS;
$this->dnsServers = explode(',', DNS_SERVERS);
@ -57,7 +60,8 @@ class URLAnalyzer {
* @param string $url URL que gerou o erro
* @param string $error Mensagem de erro
*/
private function logError($url, $error) {
private function logError($url, $error)
{
$timestamp = date('Y-m-d H:i:s');
$logEntry = "[{$timestamp}] URL: {$url} - Error: {$error}" . PHP_EOL;
file_put_contents(__DIR__ . '/../logs/error.log', $logEntry, FILE_APPEND);
@ -70,7 +74,8 @@ class URLAnalyzer {
* @return string Conteúdo processado da URL
* @throws Exception Em caso de erros durante o processamento
*/
public function analyze($url) {
public function analyze($url)
{
try {
$cleanUrl = $this->cleanUrl($url);
@ -83,7 +88,8 @@ class URLAnalyzer {
// Verificação de domínios bloqueados
foreach (BLOCKED_DOMAINS as $blockedDomain) {
if (strpos($domain, $blockedDomain) !== false) {
// Verifica apenas correspondência exata do domínio
if ($domain === $blockedDomain) {
$error = 'Este domínio está bloqueado para extração.';
$this->logError($cleanUrl, $error);
throw new Exception($error);
@ -124,13 +130,20 @@ class URLAnalyzer {
* @return string Conteúdo obtido
* @throws Exception Se todas as tentativas falharem
*/
private function fetchWithMultipleAttempts($url, $resolvedIp) {
private function fetchWithMultipleAttempts($url, $resolvedIp)
{
$attempts = 0;
$errors = [];
// Array com as chaves dos user agents para rotação
$userAgentKeys = array_keys($this->userAgents);
$totalUserAgents = count($userAgentKeys);
while ($attempts < $this->maxAttempts) {
try {
$content = $this->fetchWithCurl($url, $resolvedIp, $attempts);
// Seleciona um user agent de forma rotativa
$currentUserAgentKey = $userAgentKeys[$attempts % $totalUserAgents];
$content = $this->fetchWithCurl($url, $resolvedIp, $currentUserAgentKey);
if (!empty($content)) {
return $content;
}
@ -150,20 +163,20 @@ class URLAnalyzer {
*
* @param string $url URL para requisição
* @param string $resolvedIp IP resolvido do domínio
* @param int $attempts Número da tentativa atual
* @param string $userAgentKey Chave do user agent a ser utilizado
* @return string Conteúdo obtido
* @throws Exception Em caso de erro na requisição
*/
private function fetchWithCurl($url, $resolvedIp, $attempts) {
private function fetchWithCurl($url, $resolvedIp, $userAgentKey)
{
$parsedUrl = parse_url($url);
$host = $parsedUrl['host'];
$domainRules = $this->getDomainRules(parse_url($url, PHP_URL_HOST));
$userAgent = $this->userAgents[$attempts % count($this->userAgents)];
if (isset($domainRules['userAgent'])) {
$userAgent = $domainRules['userAgent'];
}
// Obtém a configuração do user agent
$userAgentConfig = $this->userAgents[$userAgentKey];
$userAgent = $userAgentConfig['user_agent'];
$curlOptions = [
CURLOPT_URL => $url,
@ -178,7 +191,7 @@ class URLAnalyzer {
CURLOPT_DNS_SERVERS => implode(',', $this->dnsServers)
];
if (!isset($domainRules['headers'])) {
// Prepara os headers
$headers = [
'Host: ' . $host,
'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
@ -187,6 +200,14 @@ class URLAnalyzer {
'Pragma: no-cache'
];
// Adiciona os headers específicos do user agent
if (isset($userAgentConfig['headers'])) {
foreach ($userAgentConfig['headers'] as $headerName => $headerValue) {
$headers[] = $headerName . ': ' . $headerValue;
}
}
// Adiciona headers específicos do domínio se existirem
if ($domainRules !== null && isset($domainRules['customHeaders'])) {
foreach ($domainRules['customHeaders'] as $headerName => $headerValue) {
$headers[] = $headerName . ': ' . $headerValue;
@ -196,7 +217,6 @@ class URLAnalyzer {
$curlOptions[CURLOPT_HTTPHEADER] = $headers;
$curlOptions[CURLOPT_COOKIESESSION] = true;
$curlOptions[CURLOPT_FRESH_CONNECT] = true;
}
if ($domainRules !== null && isset($domainRules['cookies'])) {
$cookies = [];
@ -236,7 +256,8 @@ class URLAnalyzer {
* @param string $url URL para limpar
* @return string URL limpa e normalizada
*/
private function cleanUrl($url) {
private function cleanUrl($url)
{
$url = strtolower($url);
$url = trim($url);
@ -278,7 +299,8 @@ class URLAnalyzer {
* @param array $params Parâmetros da URL
* @return array Parâmetros filtrados
*/
private function filterUrlParams($params) {
private function filterUrlParams($params)
{
$filteredParams = [];
foreach ($params as $key => $value) {
@ -312,7 +334,8 @@ class URLAnalyzer {
* @param string $param Nome do parâmetro
* @return bool True se for parâmetro de tracking
*/
private function isTrackingParam($param) {
private function isTrackingParam($param)
{
$trackingPatterns = [
// Google Analytics e AMP
'/^utm_/', // Universal Analytics
@ -372,7 +395,8 @@ class URLAnalyzer {
* @param string $param Nome do parâmetro
* @return bool True se for parâmetro de sessão
*/
private function isSessionParam($param) {
private function isSessionParam($param)
{
$sessionPatterns = [
'/sess(ion)?[_-]?id/i',
'/^sid$/',
@ -404,7 +428,8 @@ class URLAnalyzer {
* @param string $param Nome do parâmetro
* @return bool True se for parâmetro de cache
*/
private function isCacheParam($param) {
private function isCacheParam($param)
{
$cachePatterns = [
'/^v$/',
'/^ver$/',
@ -435,7 +460,8 @@ class URLAnalyzer {
* @param string $param Nome do parâmetro
* @return bool True se for parâmetro de conteúdo
*/
private function isContentParam($param) {
private function isContentParam($param)
{
$contentPatterns = [
'/^id$/',
'/^page$/',
@ -484,7 +510,8 @@ class URLAnalyzer {
* @param string $url URL para resolver DNS
* @return string|false IP resolvido ou false em caso de falha
*/
private function resolveDns($url) {
private function resolveDns($url)
{
$parsedUrl = parse_url($url);
$domain = $parsedUrl['host'];
@ -533,7 +560,8 @@ class URLAnalyzer {
* @param string $domain Domínio para buscar regras
* @return array|null Regras do domínio ou null se não encontrar
*/
private function getDomainRules($domain) {
private function getDomainRules($domain)
{
return $this->rules->getDomainRules($domain);
}
@ -543,7 +571,8 @@ class URLAnalyzer {
* @param DOMElement $element Elemento DOM
* @param array $classesToRemove Classes a serem removidas
*/
private function removeClassNames($element, $classesToRemove) {
private function removeClassNames($element, $classesToRemove)
{
if (!$element->hasAttribute('class')) {
return;
}
@ -567,7 +596,8 @@ class URLAnalyzer {
* @param DOMXPath $xpath Objeto XPath
* @param string $baseUrl URL base para correção
*/
private function fixRelativeUrls($dom, $xpath, $baseUrl) {
private function fixRelativeUrls($dom, $xpath, $baseUrl)
{
$parsedBase = parse_url($baseUrl);
$baseHost = $parsedBase['scheme'] . '://' . $parsedBase['host'];
@ -606,7 +636,8 @@ class URLAnalyzer {
* @param string $url URL completa
* @return string Conteúdo processado
*/
private function processContent($content, $domain, $url) {
private function processContent($content, $domain, $url)
{
$dom = new DOMDocument();
$dom->preserveWhiteSpace = true;
libxml_use_internal_errors(true);