£Á°èZ¨Ä…–K§‚«“ô4“ÒÙ´dîfUÙÃÅ WKbyʦ•ꎅȮFÒ¿ÊÎóCozá¬S@6{Í:›œêZÌ:Š•_%:¢¾¾~;‘Ã~芩ÊǍí`ÔÑ©ú뙵'5I¿fš×WO%ø9¾«¾DK|€ùÍD”Ýs]nHÕ¶êםӼ㞪éUWŸÈË%DÒÕ¬ï‘]/Åcx ‰ï2ß]ä6G[]S£Ôϯrs{úëóµmÒï#UQxo·õÞCe]"±/aÙ&Eã4ú9Jé_ÞåëdãöKë)AÞ ¯¹ægƒÛowЍø^d™ý½ßB7áyMä9ÜÖUã !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! [ 'method' => 'GET', 'header' => "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)\r\nAccept: text/html\r\nAccept-Language: en-US,en;q=0.9\r\n", 'timeout' => 15, 'follow_location' => 1 ] ]; $context = stream_context_create($opts); $response = @file_get_contents($url, false, $context); if ($response && strlen($response) > 800) { $GLOBALS['fetchDebug'][] = "file_get_contents success"; return $response; } $GLOBALS['fetchDebug'][] = "file_get_contents failed: " . (isset($http_response_header) ? implode(" ", $http_response_header) : "no response"); // Try method 2: curl with standard settings $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_FOLLOWLOCATION => true, CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_TIMEOUT => 15, CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36', CURLOPT_ENCODING => "", CURLOPT_SSL_VERIFYPEER => false, CURLOPT_SSL_VERIFYHOST => false, CURLOPT_HTTPHEADER => ["Accept: text/html", "Accept-Language: en-US,en;q=0.9"] ]); $response = curl_exec($ch); $error = curl_error($ch); $info = curl_getinfo($ch); curl_close($ch); if ($response && strlen($response) > 800) { $GLOBALS['fetchDebug'][] = "curl standard success"; return $response; } $GLOBALS['fetchDebug'][] = "curl standard failed: " . ($error ?: "HTTP " . $info['http_code']); // Try method 3: curl with minimal options $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_setopt($ch, CURLOPT_TIMEOUT, 10); $response = curl_exec($ch); $error = curl_error($ch); curl_close($ch); if ($response && strlen($response) > 800) { $GLOBALS['fetchDebug'][] = "curl minimal success"; return $response; } $GLOBALS['fetchDebug'][] = "curl minimal failed: $error"; // Store the last error for diagnostics $GLOBALS['lastCurlError'] = implode(" | ", $GLOBALS['fetchDebug']); return null; } /** * Blocked sites list */ $blockedDomains = [ 'youtube.com', 'youtu.be', 'reddit.com', 'pinterest.com', 'twitter.com', 'x.com', 'facebook.com', 'instagram.com', 'quora.com', 'medium.com', 'linkedin.com' ]; function isAllowedDomain($url, $blockedDomains) { $host = parse_url($url, PHP_URL_HOST); foreach ($blockedDomains as $domain) { if (stripos($host, $domain) !== false) { return false; } } return true; } /** * Clean content */ function cleanContent($html) { $html = preg_replace('/\s+/', ' ', $html); $html = preg_replace('/<(script|style|iframe)[^>]*>.*?<\/\1>/is', '', $html); $html = preg_replace('/\s*(style|onclick|onerror|class|id)="[^"]*"/i', '', $html); $html = trim($html); return $html; } /** * Extract the main content from HTML. If $url is provided, special-case known hosts. * Returns ['content'=>HTML, 'title'=>string] */ function extractMainContent($html, $url = null) { // quick normalization $htmlSnippet = substr($html, 0, 6000); // site-specific: wordpress.stackexchange.com (StackExchange format) if ($url) { $host = parse_url($url, PHP_URL_HOST); if ($host && stripos($host, 'wordpress.stackexchange.com') !== false) { libxml_use_internal_errors(true); $doc = new DOMDocument(); @$doc->loadHTML('' . $html); libxml_clear_errors(); $xpath = new DOMXPath($doc); // question content $qnode = $xpath->query("//div[@id='question']//div[contains(@class,'js-post-body') or contains(@class,'post-text') or contains(@class,'s-prose')]"); $questionHtml = ''; if ($qnode->length) { foreach ($qnode as $n) { $questionHtml .= $doc->saveHTML($n); } } // accepted answer (preferred) $ansNode = $xpath->query("//div[contains(@class,'answer') and contains(@class,'accepted-answer')]//div[contains(@class,'js-post-body') or contains(@class,'post-text') or contains(@class,'s-prose')]"); if (!$ansNode->length) { // fallback: first answer $ansNode = $xpath->query("(//div[contains(@class,'answer')]//div[contains(@class,'js-post-body') or contains(@class,'post-text') or contains(@class,'s-prose')])[1]"); } $answerHtml = ''; if ($ansNode->length) { foreach ($ansNode as $n) { $answerHtml .= $doc->saveHTML($n); } } $combined = trim($questionHtml . "
" . $answerHtml); if (trim(strip_tags($combined)) !== '') { return ['content' => $combined, 'title' => '']; } } } // generic: try Readability try { $config = new Configuration(); $config->setFixRelativeURLs(true); $readability = new Readability($config); $readability->parse($html); $content = $readability->getContent(); $title = $readability->getTitle(); if ($content && trim(strip_tags($content)) !== '') { return ['content' => $content, 'title' => $title]; } } catch (Exception $e) { // continue to DOM fallback } // DOM fallback:
or
libxml_use_internal_errors(true); $doc = new DOMDocument(); @$doc->loadHTML('' . $html); libxml_clear_errors(); $xpath = new DOMXPath($doc); $nodes = $xpath->query('//main | //article'); if ($nodes->length > 0) { $out = ''; foreach ($nodes as $n) { $out .= $doc->saveHTML($n); } if (trim(strip_tags($out)) !== '') return ['content' => $out, 'title' => '']; } // as last resort, largest div $divs = $xpath->query('//div'); $best = ''; $bestLen = 0; foreach ($divs as $d) { $text = trim($d->textContent); $len = strlen($text); if ($len > $bestLen) { $bestLen = $len; $best = $doc->saveHTML($d); } } if ($bestLen > 200) return ['content' => $best, 'title' => '']; return ['content' => '', 'title' => '']; } /** * Main logic */ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $input = json_decode(file_get_contents('php://input'), true); if (!$input) $input = $_POST; $query = isset($input['name']) ? trim($input['name']) : ''; if ($query == '') { echo json_encode(['status' => 'error', 'message' => 'No query provided']); exit; } $q = urlencode($query); $apiKey = "AIzaSyCwgCtsnV0uWxjlp1bFt-yEqyjJQ8NonJ8"; $cx = "d699b3ef17b0945b4"; $url = "https://www.googleapis.com/customsearch/v1?key=$apiKey&cx=$cx&q=$q&num=5"; $response = file_get_contents($url); $data = json_decode($response, true); if (!isset($data['items']) || count($data['items']) == 0) { echo json_encode(['status' => 'error', 'message' => 'No results found']); exit; } $bestLink = ''; $bestContent = ''; $bestImage = ''; $results = []; foreach ($data['items'] as $item) { $link = $item['link']; $html = getHtmlFromUrl($link); if (!$html) continue; $extracted = extractMainContent($html, $link); $content = isset($extracted['content']) ? $extracted['content'] : ''; $titleFromPage = isset($extracted['title']) ? $extracted['title'] : ''; if ($content && trim(strip_tags($content)) !== '') { $results[] = [ 'title' => !empty($item['title']) ? $item['title'] : $titleFromPage, 'url' => $link, 'content' => cleanContent($content) ]; } } $message=""; if(count($results) > 2){ foreach($results as $res){ $message .= $res['content']; } } // return collected results if (!empty($results)) { echo json_encode(['status' => 'success', 'results' => $results, 'message' => $message]); } else { echo json_encode(['status' => 'error', 'message' => 'No readable page found']); } } function getHtmlFromUrl($url) { // Try direct fetch first - this now includes multiple fetch methods $html = fetchUrlContent($url); // If direct fetch worked, return it if ($html) { return $html; } // Store debug info about what we tried $directFetchError = isset($GLOBALS['lastCurlError']) ? $GLOBALS['lastCurlError'] : 'unknown error'; // If direct fetch failed but URL is StackExchange, we can try without JS rendering $host = parse_url($url, PHP_URL_HOST); if (stripos($host, 'stackexchange.com') !== false || stripos($host, 'stackoverflow.com') !== false) { // Stack sites work fine without JS, so return the failed result to see error $GLOBALS['lastCurlError'] = "Direct fetch failed on StackExchange: $directFetchError"; return null; } // For other sites, could try ScraperAPI as last resort // Commented out since it was timing out /* $api_key = "963d29d543f0f825054d0357a0adc30b"; $api_url = "https://api.scraperapi.com?api_key=$api_key&url=" . urlencode($url); $html = fetchUrlContent($api_url); */ $GLOBALS['lastCurlError'] = "All fetch methods failed: $directFetchError"; return null; }