diff --git a/app/Models/Result.php b/app/Models/Result.php index ab0e43c8c1969c6c5238bf8e25830c9d6136c13f..70f5759752688009a9b8bc5229fe304867866b4f 100644 --- a/app/Models/Result.php +++ b/app/Models/Result.php @@ -2,9 +2,31 @@ namespace App\Models; +/* Die Klasse Result sammelt alle Informationen über ein einzelnes Suchergebnis. + * Die Results werden von den Suchmaschinenspezifischen Parser-Skripten erstellt. + */ class Result { - + public $provider; # Die Engine von der das Suchergebnis kommt + public $titel; # Der Groß Angezeigte Name für das Suchergebnis + public $link; # Der Link auf die Ergebnisseite + public $anzeigeLink; # Der tatsächlich angezeigte Link (rein optisch) + public $descr; # Die Beschreibung des Suchergebnisses + public $gefVon; # Das bei Suchergebnissen angezeigte von ... mitsamt Verlinkung + public $sourceRank; # Das Ranking für dieses Suchergebnis von der Seite, die es geliefert hat (implizit durch Ergebnisreihenfolge: 20 - Position in Ergebnisliste) + public $partnershop; # Ist das Ergebnis von einem Partnershop? (bool) + public $image; # Ein Vorschaubild für das Suchergebnis (als URL) + + public $proxyLink; # Der Link für die Seite über unseren Proxy-Service + public $engineBoost = 1; # Der Boost für den Provider des Suchergebnisses + public $valid = true; # Ob das Ergebnis noch gültig ist (bool) + public $host; # Der aus dem Link gelesene Host des Suchergebnisses + public $strippedHost; # Der Host in Form "foo.bar.de" + public $strippedDomain; # Die Domain in Form "bar.de" + public $strippedLink; # Der Link in Form "foo.bar.de/test" + public $rank; # Das Ranking für das Ergebnis + + # Erstellt ein neues Ergebnis public function __construct($provider, $titel, $link, $anzeigeLink, $descr, $gefVon, $sourceRank, $partnershop = false, $image = "", $price = 0) { $provider = simplexml_load_string($provider); @@ -24,14 +46,12 @@ class Result if ($this->sourceRank <= 0 || $this->sourceRank > 20) { $this->sourceRank = 20; } - $this->sourceRank = 20 - $this->sourceRank; if (isset($provider["engineBoost"])) { $this->engineBoost = floatval($provider["engineBoost"]->__toString()); } else { $this->engineBoost = 1; } - $this->valid = true; $this->host = @parse_url($link, PHP_URL_HOST); $this->strippedHost = $this->getStrippedHost($this->anzeigeLink); @@ -40,65 +60,92 @@ class Result $this->rank = 0; $this->partnershop = $partnershop; $this->image = $image; - - #die($this->anzeigeLink . "\r\n" . $this->strippedHost); } + /* Ranked das Ergebnis nach folgenden Aspekten: + * Startwert 0 + * + 0.02 * Sourcerank (20 - Position in Ergebnisliste des Suchanbieters) + * * Engine-Boost + */ public function rank(\App\MetaGer $metager) { - $rank = 0; + + $eingabe = $metager->getQ(); + + # Boost für Source Ranking $rank += ($this->sourceRank * 0.02); - #URL-Boost + # Boost für passende ??? URL + $rank += $this->calcURLBoost($eingabe); + + # Boost für Vorkommen der Suchwörter: + $rank += $this->calcSuchwortBoost($eingabe); + + # Boost für Suchmaschine + if ($this->engineBoost > 0) { + $rank *= floatval($this->engineBoost); + } + + $this->rank = $rank; + } + + # Berechnet den Ranking-Boost durch ??? URL + public function calcURLBoost($tmpEingabe) + { $link = $this->anzeigeLink; if (strpos($link, "http") !== 0) { $link = "http://" . $link; } - $link = @parse_url($link, PHP_URL_HOST) . @parse_url($link, PHP_URL_PATH); - $tmpLi = $link; - $tmpEingabe = $metager->getQ(); - $count = 0; - $tmpLink = ""; - + $link = @parse_url($link, PHP_URL_HOST) . @parse_url($link, PHP_URL_PATH); + $tmpLi = $link; + $count = 0; + $tmpLink = ""; + # Löscht verschiedene unerwünschte Teile aus $link und $tmpEingabe $regex = [ - "/\s+/si", - "/http:/si", - "/https:/si", - "/www\./si", - "/\//si", - "/\./si", - "/-/si", + "/\s+/si", # Leerzeichen + "/http:/si", # "http:" + "/https:/si", # "https:" + "/www\./si", # "www." + "/\//si", # "/" + "/\./si", # "." + "/-/si", # "-" ]; foreach ($regex as $reg) { $link = preg_replace($regex, "", $link); $tmpEingabe = preg_replace($regex, "", $tmpEingabe); } - #die($tmpLi . "<br>" . $link . "<br>" . $tmpEingabe . "<br><br>"); foreach (str_split($tmpEingabe) as $char) { - if (!$char || !$tmpEingabe || strlen($tmpEingabe) === 0 || strlen($char) === 0) { + if (!$char + || !$tmpEingabe + || strlen($tmpEingabe) === 0 + || strlen($char) === 0 + ) { continue; } - if (strpos(strtolower($tmpLink), strtolower($char)) >= 0) { $count++; $tmpLink = str_replace(urlencode($char), "", $tmpLink); } - if (strlen($this->descr) > 80 && strlen($link) > 0) { - #$rank += $count /((strlen($link)) * 60); - } } + if (strlen($this->descr) > 80 && strlen($link) > 0) { + return $count / ((strlen($link)) * 60); # ??? + } else { + return 0; + } + } - # Boost für Vorkommen der Suchwörter: + # Berechnet den Ranking-Boost durch das Vorkommen von Suchwörtern + private function calcSuchwortBoost($tmpEingabe) + { $maxRank = 0.1; $tmpTitle = $this->titel; $tmpDescription = $this->descr; $isWithin = false; $tmpRank = 0; - $tmpEingabe = $metager->getQ(); $tmpEingabe = preg_replace("/\b\w{1,3}\b/si", "", $tmpEingabe); $tmpEingabe = preg_replace("/\s+/si", " ", $tmpEingabe); - #die($tmpEingabe); + foreach (explode(" ", trim($tmpEingabe)) as $el) { if (strlen($tmpTitle) === 0 || strlen($el) === 0 || strlen($tmpDescription) === 0) { continue; @@ -120,35 +167,26 @@ class Result } } } - $tmpRank /= sizeof(explode(" ", trim($tmpEingabe))) * 10; - $rank += $tmpRank; - - if ($this->engineBoost > 0) { - $rank *= floatval($this->engineBoost); - } - - $this->rank = $rank; - } - public function getRank() - { - return $this->rank; + $tmpRank /= sizeof(explode(" ", trim($tmpEingabe))) * 10; + return $tmpRank; } + # Überprüft ob das Ergebnis aus irgendwelchen Gründen unerwünscht ist. public function isValid(\App\MetaGer $metager) { - # Zunächst die persönlich ( über URL-Parameter ) definierten Blacklists: + # Perönliche URL und Domain Blacklist if (in_array($this->strippedHost, $metager->getUserHostBlacklist()) || in_array($this->strippedDomain, $metager->getUserDomainBlacklist())) { return false; } - # Jetzt unsere URL und Domain Blacklist + # Allgemeine URL und Domain Blacklist if ($this->strippedHost !== "" && (in_array($this->strippedHost, $metager->getDomainBlacklist()) || in_array($this->strippedLink, $metager->getUrlBlacklist()))) { return false; } - # Nun der Eventuelle Sprachfilter + # Eventueller Sprachfilter if ($metager->getLang() !== "all") { $text = $this->titel . " " . $this->descr; $path = app_path() . "/Models/lang.pl"; @@ -160,7 +198,7 @@ class Result } - # Wir wenden die Stoppwortsuche an und schmeißen entsprechende Ergebnisse raus: + # Stopworte foreach ($metager->getStopWords() as $stopWord) { $text = $this->titel . " " . $this->descr; if (stripos($text, $stopWord) !== false) { @@ -168,7 +206,7 @@ class Result } } - # Die Strinsuche: + # Phrasensuche: $text = strtolower($this->titel) . " " . strtolower($this->descr); foreach ($metager->getPhrases() as $phrase) { if (strpos($text, $phrase) === false) { @@ -177,9 +215,10 @@ class Result } - # Abschließend noch 2 Überprüfungen. Einmal den Host filter, der Sicherstellt, dass von jedem Host maximal 3 Links angezeigt werden - # und dann noch den Dublettefilter, der sicher stellt, dass wir nach Möglichkeit keinen Link doppelt in der Ergebnisliste haben - # Diese Überprüfung führen wir unter bestimmten Bedingungen nicht durch: + /* Der Host-Filter der sicherstellt, + * dass von jedem Host maximal 3 Links angezeigt werden. + * Diese Überprüfung führen wir unter bestimmten Bedingungen nicht durch. + */ if ($metager->getSite() === "" && strpos($this->strippedHost, "ncbi.nlm.nih.gov") === false && strpos($this->strippedHost, "twitter.com") === false && @@ -192,7 +231,9 @@ class Result } } - # Unabhängig davon unser Dublettenfilter: + /* Der Dublettefilter, der sicher stellt, + * dass wir nach Möglichkeit keinen Link doppelt in der Ergebnisliste haben. + */ if ($metager->addLink($this->strippedLink)) { $metager->addHostCount($this->strippedHost); return true; @@ -201,6 +242,11 @@ class Result } } + /* Liest aus einem Link den Host. + * Dieser wird dabei in die Form: + * "http://www.foo.bar.de/test?ja=1" -> "foo.bar.de" + * gebracht. + */ private function getStrippedHost($link) { if (strpos($link, "http") !== 0) { @@ -211,6 +257,12 @@ class Result $link = preg_replace("/^www\./si", "", $link); return $link; } + + /* Entfernt "http://", "www" und Parameter von einem Link + * Dieser wird dabei in die Form: + * "http://www.foo.bar.de/test?ja=1" -> "foo.bar.de/test" + * gebracht. + */ private function getStrippedLink($link) { if (strpos($link, "http") !== 0) { @@ -222,6 +274,11 @@ class Result return $host . $path; } + /* Liest aus einem Link die Domain. + * Dieser wird dabei in die Form: + * "http://www.foo.bar.de/test?ja=1" -> "bar.de" + * gebracht. + */ private function getStrippedDomain($link) { if (preg_match("/([^\.]*\.[^\.]*)$/si", $link, $match)) { @@ -231,6 +288,7 @@ class Result } } + # Erstellt aus einem Link einen Proxy-Link für unseren Proxy-Service private function generateProxyLink($link) { if (!$link) { @@ -243,4 +301,11 @@ class Result return "https://proxy.suma-ev.de/cgi-bin/nph-proxy.cgi/en/I0/" . $tmp; } + + # Getter + + public function getRank() + { + return $this->rank; + } } diff --git a/app/Models/Searchengine.php b/app/Models/Searchengine.php index f156e30500dfb0084d71631ac6e335a216293c01..518528fc7399d00bdaff6d4111035eaf20fbd307 100644 --- a/app/Models/Searchengine.php +++ b/app/Models/Searchengine.php @@ -14,30 +14,46 @@ abstract class Searchengine use DispatchesJobs; protected $ch; # Curl Handle zum erhalten der Ergebnisse - public $fp; - protected $getString = ""; - protected $engine; - protected $counter = 0; - protected $socketNumber = null; - public $enabled = true; - public $results = []; - public $ads = []; - public $write_time = 0; - public $connection_time = 0; - public $loaded = false; - public $cached = false; + protected $getString = ""; # Der String für die Get-Anfrage + protected $engine; # Die ursprüngliche Engine XML + public $enabled = true; # true, wenn die Suchmaschine nicht explizit disabled ist + public $results = []; # Die geladenen Ergebnisse + public $ads = []; # Die geladenen Werbungen + public $loaded = false; # wahr, sobald die Ergebnisse geladen wurden + public $cached = false; + + public $ip; # Die IP aus der metager + public $gefVon; # Der HTML-Code für die Verlinkung des Suchanbieters + public $uses; # Die Anzahl der Nutzungen dieser Suchmaschine + public $homepage; # Die Homepage dieser Suchmaschine + public $name; # Der Name dieser Suchmaschine + public $disabled; # Ob diese Suchmaschine ausgeschaltet ist + public $useragent; # Der HTTP Useragent + public $startTime; # Die Zeit der Erstellung dieser Suchmaschine + public $hash; # Der Hash-Wert dieser Suchmaschine + + public $fp; # Wird für Artefakte benötigt + protected $socketNumber = null; # Wird für Artefakte benötigt + protected $counter = 0; # Wird eventuell für Artefakte benötigt + public $write_time = 0; # Wird eventuell für Artefakte benötigt + public $connection_time = 0; # Wird eventuell für Artefakte benötigt public function __construct(\SimpleXMLElement $engine, MetaGer $metager) { + # Versucht möglichst viele attribute aus dem engine XML zu laden foreach ($engine->attributes() as $key => $value) { $this->$key = $value->__toString(); } + + # Standardhomepage metager.de if (!isset($this->homepage)) { $this->homepage = "https://metager.de"; } + # Speichert die XML der Engine $this->engine = $engine->asXML(); + # Cache Standarddauer 60 if (!isset($this->cacheDuration)) { $this->cacheDuration = 60; } @@ -51,12 +67,12 @@ abstract class Searchengine return; } - # User-Agent definieren: $this->useragent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"; $this->ip = $metager->getIp(); $this->gefVon = "<a href=\"" . $this->homepage . "\" target=\"_blank\">" . $this->displayName . "</a>"; $this->startTime = microtime(); + # Suchstring generieren $q = ""; if (isset($this->hasSiteSearch) && $this->hasSiteSearch === "1") { if (strlen($metager->getSite()) === 0) { @@ -76,26 +92,30 @@ abstract class Searchengine abstract public function loadResults($result); + # ??? public function getNext(MetaGer $metager, $result) { } + # Prüft, ob die Suche bereits gecached ist, ansonsted wird sie als Job dispatched public function startSearch(\App\MetaGer $metager) { if ($this->canCache && Cache::has($this->hash)) { $this->cached = true; $this->retrieveResults($metager); } else { - # Die Anfragen an die Suchmaschinen werden nun von der Laravel-Queue bearbeitet: - # Hinweis: solange in der .env der QUEUE_DRIVER auf "sync" gestellt ist, werden die Abfragen - # nacheinander abgeschickt. - # Sollen diese Parallel verarbeitet werden, muss ein anderer QUEUE_DRIVER verwendet werden. - # siehe auch: https://laravel.com/docs/5.2/queues + /* Die Anfragen an die Suchmaschinen werden nun von der Laravel-Queue bearbeitet: + * Hinweis: solange in der .env der QUEUE_DRIVER auf "sync" gestellt ist, werden die Abfragen + * nacheinander abgeschickt. + * Sollen diese Parallel verarbeitet werden, muss ein anderer QUEUE_DRIVER verwendet werden. + * siehe auch: https://laravel.com/docs/5.2/queues + */ $this->dispatch(new Search($this->resultHash, $this->host, $this->port, $this->name, $this->getString, $this->useragent)); } } + # Ruft die Ranking-Funktion aller Ergebnisse auf. public function rank(\App\MetaGer $metager) { foreach ($this->results as $result) { @@ -103,6 +123,7 @@ abstract class Searchengine } } + # Magic ??? private function setStatistic($key, $val) { @@ -112,6 +133,7 @@ abstract class Searchengine $this->$key = $newVal; } + # Entfernt wenn gesetzt das disabled="1" für diese Suchmaschine aus der sumas.xml public function enable($sumaFile, $message) { Log::info($message); @@ -125,6 +147,7 @@ abstract class Searchengine fclose($this->fp); } + # Öffnet einen neuen Socket für diese Engine public function getSocket() { $number = Redis::hget('search.' . $this->hash, $this->name); @@ -136,6 +159,7 @@ abstract class Searchengine } } + # Fragt die Ergebnisse von Redis ab und lädt Sie public function retrieveResults(MetaGer $metager) { if ($this->loaded) { @@ -169,6 +193,7 @@ abstract class Searchengine Redis::del($this->host . "." . $this->socketNumber); } + # Erstellt den für die Get-Anfrage genutzten Host-Link protected function getHost() { $return = ""; @@ -181,26 +206,7 @@ abstract class Searchengine return $return; } - public function getCurlInfo() - { - return curl_getinfo($this->ch); - } - - public function getCurlErrors() - { - return curl_errno($this->ch); - } - - public function addCurlHandle($mh) - { - curl_multi_add_handle($mh, $this->ch); - } - - public function removeCurlHandle($mh) - { - curl_multi_remove_handle($mh, $this->ch); - } - + # Erstellt den für die Get-Anfrage genutzten String private function generateGetString($query, $url, $language, $category) { $getString = ""; @@ -218,32 +224,39 @@ abstract class Searchengine } # Wir müssen noch einige Platzhalter in dem GET-String ersetzen: + # Useragent if (strpos($getString, "<<USERAGENT>>")) { $getString = str_replace("<<USERAGENT>>", $this->urlEncode($this->useragent), $getString); } + # Query if (strpos($getString, "<<QUERY>>")) { $getString = str_replace("<<QUERY>>", $this->urlEncode($query), $getString); } + # IP if (strpos($getString, "<<IP>>")) { $getString = str_replace("<<IP>>", $this->urlEncode($this->ip), $getString); } + # Language if (strpos($getString, "<<LANGUAGE>>")) { $getString = str_replace("<<LANGUAGE>>", $this->urlEncode($language), $getString); } + # Category if (strpos($getString, "<<CATEGORY>>")) { $getString = str_replace("<<CATEGORY>>", $this->urlEncode($category), $getString); } + # Affildata if (strpos($getString, "<<AFFILDATA>>")) { $getString = str_replace("<<AFFILDATA>>", $this->getOvertureAffilData($url), $getString); } return $getString; } + # Wandelt einen String nach aktuell gesetztem inputEncoding dieser Searchengine in URL-Format um protected function urlEncode($string) { if (isset($this->inputEncoding)) { @@ -253,6 +266,7 @@ abstract class Searchengine } } + # Liefert Sonderdaten für Yahoo private function getOvertureAffilData($url) { $affil_data = 'ip=' . $this->ip; @@ -271,4 +285,26 @@ abstract class Searchengine { return $this->enabled; } + + # Artefaktmethoden + + public function getCurlInfo() + { + return curl_getinfo($this->ch); + } + + public function getCurlErrors() + { + return curl_errno($this->ch); + } + + public function addCurlHandle($mh) + { + curl_multi_add_handle($mh, $this->ch); + } + + public function removeCurlHandle($mh) + { + curl_multi_remove_handle($mh, $this->ch); + } }