Aceasta este o clasa prin care se obtin rezultatele cautarii de pe Google pentru un anume site sau global.
Concret, in principal poate fi utilizata pentru a adauga pe site un sistem de cautare cu rezultate obtinute din paginile indexate de google pt. acel site.
Are doua moduri de Search, unul pentru pagini din site-ul in care e folosita clasa, iar al doilea pt. global (site-urile de pe web). Cand se face cautarea doar pt. pagini din site-ul curent, rezultatul cautarii e salvat in fisiere pe server, precum si cuvintele cautate.
Pe langa datele cautarii din paginile indexate de Google, cu aceasta clasa se poate obtine lista cu termenii cautati si un top al acestora.
<?php
if(!isset($_SESSION)) session_start(); // Daca sesiunea nu e activata, o acctiveaza
// Clasa Search ( www.marplo.net )
class Search {
// Proprietati
protected $site; // Site-ul pt. care se face cautarea
protected $cauta; // Expresia cautata
private $google; // Adresa Google de cautare
public $nr_res = 50; // Numarul de rezultate pt. cautare
// Statice
static protected $domain;
static private $dir_cachesrc = 'cachesrc/'; // Directorul in care sunt salvate fisierele cu cautarile
static private $file_allsrc = 'cachesrc/allsrc.txt'; // Fisierul in care e stocata lista de cautari
static private $ext = '.htm';
const SEP = '^'; // Separator de date pe randurile din $file_allscr
// Proprietati Regex de cautare /(link) (titlu) (descriere)/
static protected $reg_google = '/\<h3 class="r"\>\<a href="([^"]+)"(.*?)\>(.*?)\<\/a\>\<\/h3\>(.*?)\<div class="s"\>(.*?)\<br\>/i';
// Constructor
function __construct($site='') {
self::$domain = str_replace('www.', '', $_SERVER['HTTP_HOST']); // seteaza prop. 'domain' domeniul site-ului
// Daca parametru $site nu e completat, atribuie la prop. 'site' domeniu curent (daca e diferit de loclahost)
// Daca e un sir cu cel putin 3 caractere, atribuie prin setSite() valoarea la prop 'site'
// Altfel, returneaza eroare
if(strlen($site)==0) $this->site = $_SERVER['HTTP_HOST']=='localhost' ? '' : str_replace('www.', '', $_SERVER['HTTP_HOST']);
else if(is_string($site) && strlen($site)>2) $this->setSite(trim($site));
else throw new Exception('Valoare incorecta pt. $site');
}
// Metoda Accesor - seteaza valoarea pt. site
public function setSite($site) {
// Daca parametru e 'www' sau se potriveste tiparului RegExp, atribuie valoarea la prop. "site"
if($site=='www' || preg_match('/^(http:\/\/|https:\/\/|<www\.)?[a-z0-9\._-]+.[info|net|com|gov|ro|md|eu]$/i', $site)) {
// Face numele de site fara www.
$ar_del = array('https://', 'http://', 'www.', 'www');
$site = str_replace($ar_del, '', $site);
$this->site = $site;
}
else throw new Exception('Valoare incorecta pt. site');
}
// Metoda care returneaza continutul unei pagini din $adr, preluat prin cURL sau file_get_context
private function curlSearch($adr) {
// Creaza o matrice ce stocheaza mai multe tipuri de agenti (browsere)
$agents[] = 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; WOW64; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.0.04506; Media Center PC 5.0)';
$agents[] = 'Opera/9.63 (Windows NT 6.0; U; ru) Presto/2.1.1';
$agents[] = 'Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.5) Gecko/2008120122 Firefox/3.0.5';
// Daca poate initializa resursa curl
if ($ch = curl_init()) {
curl_setopt($ch, CURLOPT_URL, $adr); // Apeleaza adresa URL specificata
// Trimite header-ele necesare
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_USERAGENT, array_rand($agents, 1)); // Cu agent ales random
$str = curl_exec($ch); // Preia continutul returnat intrun sir
curl_close($ch); // Inchide resursa curl
return $str;
}
else if ($str = file_get_contents($adr)) return $str;
else return false;
}
// Returneaza un Array cu datele (link, titlu, descriere), bazate pe o expresie Regexp
private function regexGetData($reg, $str) {
$ar_re = array();
$nr_re = preg_match_all($reg, $str, $ar_dat); // Preia numarul de date gasite si datele in $ar_dat
// Daca preg_match_all gaseste cel putin un rezultat
// Parcurge datele si adauga in $ar_re Array-uri cu: link, titlu, descriere
if($nr_re>0) {
for($i=0; $i<$nr_re; $i++) {
// get the link
if(preg_match('/http:\/\/(.*?)&sa/i', $ar_dat[1][$i], $ml)) $link = 'http://'.$ml[1];
else $link = '';
$ar_re[$i]['link'] = $link;
$ar_re[$i]['titl'] = strip_tags($ar_dat[3][$i]); // Sterge tag-urile
$ar_re[$i]['desc'] = strip_tags($ar_dat[5][$i], '<em>'); // Pastreaza tag-uri <em>
}
}
return $ar_re;
}
// Metoda care face cautarea
private function makeSearch() {
// Adresa de cautare, la prop. "site" si cuvantul cu urlencode()
$this->google = 'http://www.google.ro/search?as_q='. urlencode($this->cauta). '&hl=ro&num='. $this->nr_res. '&btnG=C%C4%83utare+Google&as_sitesearch='. $this->site. '&as_rights=&safe=images';
// Preia datele returnate de curlSearch() si le afiseaza
$str = $this->curlSearch($this->google);
// Apeleaza functia care separa cu RegExp datele necesare intr-un multi-Array cu: link, titlu, descriere
$ar_dat = $this->regexGetData(self::$reg_google, $str);
$nr_re = count($ar_dat); // Nr. rezultate primite
$re_html = ''; // Va stoca datele ce trebuie returnate
// Daca e cel putin un rezultat primit, parcurge datele si le aduga in tag-uri HTML
// Altfel, seteaza 'Nu au fost date gasite'
if($nr_re>0) {
for($i=0; $i<$nr_re; $i++) {
// Definire tip tag Hx pt. titlu
if($i<4) $hx = 'h2';
else if($i<14) $hx = 'h3';
else if($i<34) $hx = 'h4';
else $hx = 'h5';
$re_html .= '<'.$hx.'>'.($i+1). '. <a href="'. $ar_dat[$i]['link']. '" title="'. $ar_dat[$i]['titl']. '">'. $ar_dat[$i]['titl']. '</a></'.$hx.'>'. $ar_dat[$i]['desc']. "\r\n";
}
}
else $re_html = false;
return $re_html;
}
// Metoda prin care se obtine cautarea (ori din fisier salvat, ori prin metoda "makeSearch()")
public function getSearch($cauta) {
// Daca Sesiunea 'src' exista si e mai noua de 1 min, afiseaza mesaj si intrerupe scriptul
// Altfel, creaza sesiunea cu timpul
if(isset($_SESSION['src']) && (time()-$_SESSION['src'])<60) {
$re_src = 'Se poate efectua o cautare pe minut';
}
else {
$_SESSION['src'] = time();
// Daca $cauta are adaugata valoare, cel putin 3 caractere, o atribuie cu litere mici la proprietatea 'cauta'
if(strlen($cauta)>2) $this->cauta = strtolower(strip_tags(trim($cauta)));
// Preia filtrata proprietatea cauta
$filtr_cauta = preg_replace('/[^a-z 0-9_\.-]+/i', '', $this->cauta);
$file_src = self::$dir_cachesrc. str_replace(' ', '_', $filtr_cauta). self::$ext; // Adresa si numele fisierului
// Daca prop. 'site' e aceeasi cu static 'domain' cauta fisierul daca s-a mai facut acea cautare sau apeleaza metoda makeSearch()
// Altfel, apeleaza makeSearch()
if($this->site===self::$domain) {
// Daca fisierul de cache nu exista sau e prea vechi (zile 5+)
// preia datele de la makeSearch() si pune fisierul pe server
if((!file_exists($file_src)) || (filesize($file_src) == 0) || (time()-filemtime($file_src) > 43200)) {
$re_src = $this->makeSearch();
// Daca $re_src e TRUE, aplica salvare fisierului, Altfel, seteaza mesaj de eroare
if($re_src) {
if(!file_put_contents($file_src, $re_src)) echo 'Fisierul '. $filtr_cauta. ' nu poate fi salvat';
}
else $re_src = '<h4>Nu au fost gasite rezultate pentru <em>'. $this->cauta. '</em> pe Site <i>www.'. $this->site. '</i> , incercati Web.</h4>';
}
else $re_src = file_get_contents($file_src);
$this->addSearch(); // Apelare metoda care adauga intr-un fisier termenii cautati
}
else $re_src = $this->makeSearch();
}
return $re_src;
}
// Adauga in fisierul din prop. 'file_allsrc' cautarea (cauta^timp^nr)
private function addSearch() {
$ad_cauta = $this->cauta;
$row = $ad_cauta.self::SEP.time().self::SEP.'1'; // Randul ce trebuie adaugat
$i = 0; // Indice unde trebuie adaugat randul
// Daca fisierul exista, preia intr-un Array randurile din el
if(is_file(self::$file_allsrc)) {
$ar_rows = file(self::$file_allsrc, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$nr_rows = count($ar_rows);
// Parcurge randurile, cu explode() la fiecare
// Daca exista deja un rand cu $ad_cauta, il actualizeaza si intrerupe parcurgerea
for($i=0; $i<$nr_rows; $i++) {
$row_ar = explode(self::SEP, $ar_rows[$i]);
if($row_ar[0]==$ad_cauta) {
$row = $ad_cauta.self::SEP.time().self::SEP.($row_ar[2]+1); // Actualizeaza randul ce va fi adaugat
break;
}
}
}
// Adauga si randul nou, unde indica (a ajuns) $i
$ar_rows[$i] = $row;
// Rescrie randurile in fisier
if(!file_put_contents(self::$file_allsrc, implode("\r\n", $ar_rows))) echo 'Fisierul '. self::$file_allsrc. ' nu poate fi salvat';
}
// Metoda preia lista cu toate cautarile si returneaza ultimile $nr
public function getListSrc($nr=10, $tip='last') {
$ar_list = array(); // Va contine lista cu cautarile aranjate
$re_html = '<ol>'; // Va contine codul HTML cu lista ce va fi returnata
// Definire indice pt. aranjare (1=dupa data, 2=dupa nr.) in functie de $tip
$k = ($tip=='top') ? 2 : 1;
// Daca fisierul exista, preia intr-un Array randurile din el
if(is_file(self::$file_allsrc)) {
$ar_rows = file(self::$file_allsrc, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$nr_rows = count($ar_rows);
// Parcurge randurile, cu explode() la fiecare, si aranjeaza intr-un Array dupa data
for($i=0; $i<$nr_rows; $i++) {
$row_ar = explode(self::SEP, $ar_rows[$i]);
$ar_list[$row_ar[$k]] = $row_ar[0];
}
krsort($ar_list); // Aranjeaza datele descrescator dupa valoarea cheilor
$nr = min($nr_rows, $nr); // Nr. randuri ce vor fi returnate
// Daca e cel putin un rand
if($nr>0) {
$ar_list = array_slice($ar_list, 0, $nr); // Retine doar primele $nr elemente
// Parcurge Array-ul si adauga randurile in codul html ce va fi returnat
$nr = count($ar_list);
for($i=0; $i<$nr; $i++) { $re_html .= '<li>'. $ar_list[$i]. "</li>\r\n"; }
}
}
$re_html .= '</ol>';
return $re_html;
}
}
?>
- Clasa e setata sa faca maxim o cautare pe minut, pentru a evita spamm-ul.<form action="search.php" method="get"> <input type="text" name="sh" size="18" maxlength="40" /> <input type="submit" value="Cautare" /><br /> <input type="radio" name="w" id="ws" value="1" checked="checked" /><label for="ws">Site</label> <input type="radio" name="w" id="ww" value="www" /><label for="ww">Web</label> </form>
<?php
include('class.Search.php'); // Include Clasa
// Daca sunt primite date de la formular, prin GET['sh'] si GET['w']
if(isset($_GET['sh']) && isset($_GET['w'])) {
$term = strip_tags(trim($_GET['sh'])); // Sterge posibile tag-uri din termenii cautati
$site = (isset($_GET['w']) && $_GET['w']=='www') ? 'www' : ''; // Definire argument $site pt. instanta
// Daca $term are cel putin 3 caractere, foloseste clasa Search
// Altfel, defineste $src cu mesaj
if(strlen($term)>2) {
$objSrc = new Search($site); // Instanta de obiect la clasa Search
echo 'Lista'. $objSrc->getListSrc(12); // Afiseaza ultimii 12 termeni cautati
echo 'Top'. $objSrc->getListSrc(10, 'top'); // Afiseaza Top 10 termenii cei mai cautati
echo $objSrc->getSearch($term); // Afiseaza rezultatul cautarii
$objSrc->nr_res = 30; // Seteaza nr. maxim de rezultate la 30
$objSrc->setSite('www'); // Modifica domeniul de cautare la global, pe Web
// Acum, o noua apelare $objSrc->getSearch($term); va efectua cautarea pe Web, cu maxim 30 rezultate
}
else echo 'Termenul cautat trebuie sa contina intre 3 si 40 caractere, fara tag-uri.';
}
?>
- Explicatiile sunt in comentariile din cod.