Morjensta kaikki!
Teen sivuilleni hakukonetta, ja kiinnostaisi tietää miten saan tulostettu kohdan sivusta kuten Google. Eli, ei käyttäjälle varmaan sano mitään, jos tulostetaan vain, että "Sivulta xxx löytyi hakusana xxx". Sillä pitäisi nähdä siis, että mitä muuta sisältöä siellä on.
Tässä tämä minun härvelini:
<?php $folder = opendir("."); $word = "auto kana teksti"; $words = explode(" ", $word); $loytyneet = 0; $loytyi = ""; $dontshow = array("haku.php", "eisaanayttaa.php"); //Käydään jokainen tiedosto läpi while($info = readdir($folder)) { //Jos $info on ., .. tai arrayssa, niin ohitetaa if($info == "." OR $info == ".." OR in_array($info, $dontshow)) continue; //Tiedoston sisältö on $file muuttujassa $file = file_get_contents($info); //Käydään niin monta kertaa läpi, kuin hakusanoja on for($i = 0; $i < sizeof($words); $i++) { $kierrokset = sizeof($words); if($tiedosto == 0) { $loytyi .= "<p>\nTiedostosta $info löytyi seuraavat hakusanat:<ul>\n"; $tiedosto = 1; } if($i == $kierrokset - 1) $tiedosto = 2; if(strpos($file, $words[$i]) !== false) { //Löytyi $loytyi .= "<li>" . $words[$i] . "</li>\n"; if($viime != $info) $loytyneet++; } if($tiedosto == 2) $loytyi .= "</ul>\n</p>\n\n"; $viime = $info; } $tiedosto = 0; } echo "<p><h3>Löytyi $loytyneet hakutulosta</h3></p>\n\n$loytyi"; ?>
Tuo nyt listaa hakutulokset tähän tyyliin:
Löytyi 2 hakutulosta Tiedostosta auto.txt löytyi seuraavat hakusanat: auto teksti Tiedostosta lol.php löytyi seuraavat hakusanat: kana Tiedostosta testi.txt löytyi seuraavat hakusanat: auto kana teksti
Ota vaikka talteen strpos-funktion ilmoittama kohta ja leikkaa substr-funktiolla tämän ympäriltä sata merkkiä kumpaankin suuntaan.
Jollakin tavalla pitäisi siis tunnistaa tekstimassasta lause. Lause alkaa isolla alkukirjaimella, sekä päättyy pisteeseen. Onko se sinusta riittävän säännöllinen, jotta esimerkiksi säännöllinen lauseke voisi olla ratkaisu? Toisaalta, kuten äskeisestä lauseesta huomattiin, niin lause voi päättyä myös kysymysmerkkiin. Ehkä parempi hakea kuitenkin haettu sana ja siitä vaikka juuri 100 merkkiä taakse- ja eteenpäin.
Voit etsiä pisteet (muista myös kysymysmerkki ja huutomerkki!) strpos- ja strrpos-funktioilla. Funktiolle voi antaa parametriksi kohdan, josta haku alkaa. Toistamalla hakua pari kertaa saat useamman virkkeen.
Edit. Jaha, poistit viestisi. ^^
Jep, ehdin poistamaan kun tajusin virheeni. Sellainen kysymys vielä, että jos sivulla lukee esimerkiksi [b]moi[/b], niin miten voin säännöllisillä lausekkeilla hakea tuon [b]-tagien sisällön? En ole koskaan oikein ymmärtänyt tätä logiikkaa. (Piti laittaa välilyönnit tuonne tageihin, kun menee muuten paksuksi =))
Säännöllisistä lausekkeista on hyvä opas.
Tiedän, että täällä on sellainen.
[otsikko]Kanala[/otsikko] kana
Tuollainen sivu, ja tälläinen koodi:
<?php echo preg_replace("/\[otsikko\](.*?)\[\/otsikko\]/is", "$1", $sivu);
Tulostaa Kanala kana, kun pitäisi tulla Kanala. Jos muutan $1:n $2:ksi, niin tulee "kana".
Tuo lopettaa lukemisen juurikin tuon [/otsikko] jälkeen, joten kana ei "mahdu" tuohon lausekkeeseen. Lisää lausekkeen loppuun vaikka .+, jolloin tuon tulisi toimia ihan oikein.
Korvaat säännöllisen lausekkeen mukaisen kohdan tekstistä ja tulostat syntyneen tekstin. Säännöllinen lauseke on aivan oikein (lähes; \-merkit pitäisi oikeastaan kirjoittaa kahtena, koska \\ muuttuu \:ksi jo normaalissa PHP:n tekstinkäsittelyssä ja \ on osa säännöllistä lauseketta). Esimerkkisi toimii käytännössä näin:
<?php echo str_replace("[otsikko]Kanala[/otsikko]", "Kanala", $sivu);
Lausekkeen löytämä kohta korvataan siis uudella, ja lopuksi koko teksti (myös lausekkeen ulkopuoliset osat) tulostetaan.
Sinun pitäisi siis käyttää preg_match(_all)-funktiota, jolla vain poimitaan osuma(t) tekstistä. Oppaasta valitettavasti puuttuvat nämä käytännölliset esimerkit, joissa funktion löytämä teksti otettaisiin talteen.
<?php // Haetaan kaikki osumat; jos yksi riittää, ota _all pois. if (preg_match_all('/lause/', $sivu, $osumat, PREG_SET_ORDER)) { foreach ($osumat as $osuma) { // $osuma[0] == koko osuma, "[otsikko]Kanala[/otsikko]" // $osuma[1] == ensimmäinen sulkulauseke, "Kanala" } }
Jee, kiitos Metabolix! Nyt se toimii hienosti =)
No, nyt toimii vielä paremmin. =) Silti olisi vielä kysymys: Miten saan formin menemään osoitteeseen index.php?sivu=haku&hakusana=formistatullutgettieto? Menee aina vain index.php?hakusana=xxx.
Jos sulla on <form method="get" action="index.php?mitävaandiipadaapaa">, niin silloin kaikki actionissa ?-merkin jälkeen oleva korvataan sillä, mitä formilta tulee.
Eli jos haluat siihen muita tietoja, niin lisää ne formille
<form method="get" action="index.php"> <input type="hidden" name="sivu" value="haku" /> <input type="text" name="hakusana" /><input type="submit" value="Hae" /> </form>
Kiitos Grez =)
Pitää vielä kysyä, että mitä teen tälle, että saan sen hakemaan tietoa myös alihakemistoista?
<?php //Hakusanat erotettuna välilyönnillä $hakusana = explode(" ", $_GET["hakusana"]); //Löytyneitä sivuja $loytynyt = 0; //Näitä sivuja ei käsitellä $ei = array("haku.php", "index.php"); $hakemisto = opendir("."); while($info = readdir($hakemisto)) { if($info == "." OR $info == ".." OR in_array($info, $ei)) continue; //Haetaan $file muuttujaan $info tiedoston sisältö $file = file_get_contents($info); $sivunnimi = explode(".", $info); //Haetaan sivun otsikko if (preg_match_all('/\[otsikko\](.*?)\[\/otsikko\]/is', $file, $osumat, PREG_SET_ORDER)) { foreach ($osumat as $osuma) { $otsikko = $osuma[1]; } } //Jos otsikko oli tyhjä, tai sen pituus oli nolla merkkiä if(empty($otsikko) || strlen($otsikko) <= 0) $otsikko = "Unnamed site"; $file_lower = strtolower($file); for($b = 0; $b < sizeof($hakusana); $b++) { if(strpos($file_lower, strtolower($hakusana[$b])) !== false) { $sanansijainti = strpos($file_lower, strtolower($hakusana[$b])); $sijainti = $sanansijainti - 75; $kooste = substr($file, $sijainti, 150); $kooste = str_replace($hakusana[$b], "<b>" . $hakusana[$b] . "</b>", $kooste); $kooste = preg_replace('/\[otsikko\](.*?)\[\/otsikko\]/is', '', $kooste); $sisalto .= "<p>\n"; $sisalto .= "<a style=\"color: #8C0707\" href=\"index.php?act=" . $sivunnimi[0] . "\">$otsikko:</a>\n<ul>\n"; $sisalto .= "$kooste..."; $sisalto .= "<br><font style=\"color: green; font-size: 9pt\">http://" . $_SERVER["SERVER_NAME"] . "/MPS/$info</font></ul>\n</p>\n\n"; } } $otsikko = ""; } if(strlen($_GET["hakusana"]) >= 1) { if($loytynyt == 0) echo "Ei yhtään tulosta hakusanalla " . $_GET["hakusana"] . "<br>"; else if($loytynyt == 1) echo "$loytynyt hakutulos löytynyt:<br>"; else echo "$loytynyt hakutulosta löytynyt:<br>"; } echo $sisalto; ?>
Nyt tuo antaa vaan 403 virheilmoituksen, kun tulee hakemisto vastaan (Tuo file_get_contents-rivi).
Rekursiivisella funktiolla. Kannattaa lukea rekursio-opas, siellä on itse asiassa aivan samanlainen esimerkki.
<?php function hae_tiedostot($polku, &$taulukko = null) { if ($taulukko === null) { $uloin = true; $taulukko = array(); } $hakemisto = opendir($polku); while ($info = readdir($hakemisto)) { if ($info == '.' || $info == '..') continue; if (is_dir($info)) { hae_tiedostot("$polku/$info", $taulukko); } else { $taulukko[] = "$polku/$info"; } } closedir($hakemisto); if ($uloin) { return $taulukko; } } $tiedostot = hae_tiedostot("."); foreach ($tiedostot as $polku) { $nimi = basename($polku); $hakemisto = dirname($polku); echo "Tiedosto $nimi on hakemistossa $hakemisto; koko polku on $polku.\n"; // file_get_contents($polku); }
Hei, kiitos taas! =)
Aihe on jo aika vanha, joten et voi enää vastata siihen.