V tomto návode si ukážeme ako sme vyriešili problém, ktorý špecifikoval náš zákazník. Jeho požiadavky boli nasledovné:
1. vyhľadaj akékoľvek kľúčové slovo v stránke http://www.prweb.com
2. všetky nájdené výsledky by sa mali spracovať. Nielen prvých 10 nájdených výsledkov, ale tiež ďalšie stránky (napríklad pre kĽúčové slovo "black coffe" to bolo viac ako 1600 nájdených článkov)
3. každý nájdený článok by mal byť otvorený a jeho obsah stiahnutý do súboru s názvom: {$rok}-{$mesiac}-{$id}.html
Zákazník sa nás opýtal, či UnitMiner dokáže splniť takúto požiadavku a my sme odpovedali veľkým "ÁNO", pretože presne na takýto druh požiadaviek je Unit Miner stavaný. Taže začneme tento návod s tým, ako spraviť takúto úlohu s UnitMinerom.
Ako prvý krok si vytvoríme tag Logger, pretože počas vývoja skriptu je vždy dobré vedieť, čo sa deje vnútri UnitMineru. Aj keď rozumiem UnitMineru, logujem zakaždým, keď robím nový skript alebo keď natrafím na nejaký problém.
V prvom kroku si tiež vytvoríme malú kostru zo sekcie main, ktoú už každý pozná. Takže si vytvoríme skript main.w napríklad v adresári Wrapper/samples/prweb
#defines logger, which will log all debug messages
<Logger File>
Global
#store output of logger to file
FileName output-debug.txt
Level debug
</Logger>
#main section
<Section>
Name main
</Section>
Main main
Hlavný článok je vyznačený v zdrojovom kóde:
V tomto kroku Vám ukážem ako vytvoriť jednoduchý HTML dokument, ktorý bude obsahovať formulár s jedným políčkom na vloženie textu. Tiež Vám ukážem ako spustiť UnitMiner skript, keď sa zadá hocijaký hľadaný reťazec.
Takže, vytvorme súbor index.php v adresári Wrapper/samples/prweb. Vytvorte si adresáre, ak neexistujú. Vnútri súboru bude HTML sekcia, ktorá vytvorí formulár a php sekcia, ktorá spustí UnitMiner skript s názvom main.w.
Chceli by sme extrahovať iba titulok článku a krátky text pod obrázkom. Ako vidíme, titulok je ohraničený tagmi <div class="cnnMainT1Hd"> … </div> a krátky text je medzi <div class="cnnMainT1"> … </div>
<form>
Search string: <input type="text" name="search" value="<? echo $_REQUEST['search']; ?>"></input>
<input type="submit" name="Execute">
</form>
<?
if (strlen($_REQUEST['search'])) {
require_once('../../../QUnit/Global.class.php');
$executor = QUnit_Global::newobj('Wrapper_Executor', 'main.w');
$executor->execute();
}
?>
Teraz sa vrátime k nášmu novému main.w skriptu.
Do našej prázdnej kostry pridáme príkaz, ktorý načíta hľadaný reťazec (hodnota poľa "search"). Pre tieto účely použijeme tag <Action Template>, ktorý nám umožní vykonať akýkoľvek php kód. V tomto tagu vytvoríme URL, ktorá sa používa pri hľadaní na stránke www.prweb.com.
Ako ďalšie v tomto kroku načítame obsah, ktorý vráti hľadanie. Pre toto použijeme tag <Action ContentURL>. A ako posledné, spustíme nový skript (ktorý ešte nemáme) s názvom "process_result_page.w".
Tento nový skript bude spracuvávať všetko, čo sa nájde na výslednej stránke - to znamená, zachytí URLky nájdených článkov.
Každý skript obsahuje hlavnú sekciu, ktorá stiahne stránku z požadovanej URL a potom niečo spraví s jej obsahom. V nasledujúcom kroku sa pozrieme ako zachytiť dáta.
<Logger File>
Global
FileName output-main.txt
Level debug
</Logger>
<Section>
Name main
#Set variable name $url (loaded value from REQUEST - form input field search)
<Action Template>
TemplateText $context->setVariable('$url', \
"http://www.prweb.com/cgi-bin/search/search.pl?Terms=" . $_REQUEST['search'] . \
"&Match=0&Realm=prweb_inject&submit=Search");
</Action>
<Action ContentURL>
URL {$url}
</Action>
#process found resultset
<Action Eval>
File process_result_page.w
</Action>
</Section>
#start execution with section named: main
Main main
V predchádzajúcom kroku sme chceli spustiť skript s názvom process_result_page.w. Takže si ukážeme ako vytvoriť tento skript.
Vytvorte si prosím súbor s názvom process_result_page.w v tom istom adresári ako je súbor main.w. Vnútri skriptu načítame obsah stránky s výsledkami hľadaní (URLka je uložená v premennej s názvom $url). Pridáme while cyklus, ktorý pôjde po všetkých zachytených reťazcoch v dokumente. Vnútri sekcie While zadefinujeme porovnávací reťazec Pattern, ktorý bude prehľadávať obsah stránky a zachytí želané hodnoty (linky na články). A konečne spustíme skript "process_pr_page.w", ktorý bude vyhodnocovať každý článok zvlášť.
Aby sme správne vytiahli dáta, musíme špecifikovať porovnávajúci výraz. Nasledujúci výraz povie systému, aby vytiahol všetko medzi tagmi <div class="cnnMainT1Hd"><h2><a*>...</a></h2></div> a uložil vytiahnutý obsah do premennej $main_title
Potom si definujeme, čo spravíme s hodnotou premennej. V našom prípade ju len vypíšeme na štandardný výstup pomocou príkazu Text, no môžete si ju uložiť do súboru, spraviť insert do databázy alebo použiť túto premennú na stiahnutie ďalšej stránky.
<Section>
Name process_result_page
#load content from url defined in context variable $url
<Action ContentURL>
URL {$url}
#from retrieved content remove new line breakes
RemoveNewLine
</Action>
#iterate in page until you find all links to PR articles
<Section While>
#match pattern which contains link to PR article and store link into context variable $link_url
<Pattern>
RegExp <dt><b>{$link_number}. <a href="{$link_url}">
</Pattern>
#execute script, which will process matched URL of PR article
<Action Eval>
# some pages have different format and they don't match defined patterns,
# therefore continue in execution also if any page fails
Optional
File process_pr_page.w
</Action>
</Section>
</Section>
#start execution with section process_result_page
Main process_result_page
Tu sme si zadefinovali ešte jeden výraz, ktorý vytiahne všetko medzi tagmi <div class="cnnMainT1">...</div> a uloží hodnotu do premennej $short_text.
Všimnite si, že sme použili špeciálny výraz :re(.*?) po premennej.
:re hovorí systému, že použijeme regulérny výraz na vytiahnutie textu
.*? je regulérny výraz, ktorý namapuje všetky znaky po znak ‘<’.
Tiež sme zadefinovali ešte jednu Action, ktorá vypíše vytiahnutý text na štandardný výstup.
Už sa blížime k ukončeniu našej úlohy. V tomto kroku potrebujeme zapísať obsah stránky s článkom do súboru, tak ako je to v špecifikácii. Takže vytvoríme súbor s názvom "process_pr_page.w" v tom istom adresári ako predchádzajúce súbory.
V tomto skripte načítame obsah stránky s URLkou v premennej $link_url z predchádzajúceho skriptu. Tiež zachytíme dáta z článku (titulok a text). Ako posledné, uložíme dáta do súboru.
<Section>
Name process_pr_page
#load content of page containing PR article
<Action ContentURL>
#url is stored in context variable $link_url
URL {$link_url}
#remove line breaks from loaded content
RemoveNewLine
</Action>
#match titel of article
<Pattern>
RegExp <h1 class="h1format">{$pr_title}</h1>
</Pattern>
#match text of PR article
<Pattern>
RegExp <div align="left">{$pr_text:regexp(.*?)}</div>
</Pattern>
#load variable $link_url as content, because we like to parse from url year, month and id,
#which we will use as filename
<Action ContentVariable>
Variable $link_url
</Action>
#match year, month and id in content
<Pattern>
RegExp releases/{$year}/{$month}/prweb{$id}.htm
</Pattern>
#store matched data to file, where filename will have format e.g. 2005-1-212133.html
#formatting of file defines attribute Text
<Action Print>
FileName {$year}-{$month}-{$id}.html
Text <HTML><BODY><H1>{$pr_title}</H1><br><br>{$pr_text}</BODY></HTML>
</Action>
</Section>
#start execution in this script with section process_pr_page
Main process_pr_page
Predtým som tvrdil, že už sme skoro hotoví.
Áno, to je pravda, ale zabudli sme na jednu vec zo špecifikácie a to, že musíme prejsť všetky nájdené stránky. Takže toto spravíme v poslednej časti návodu.
Musíme opäť upraviť skript main.w, pretože v tomto skripte načítavame prvú stránku výsledkov.
V tomto skripte zachytíme URL nasledujúcich stránok a otvoríme ich tým istým skriptom ako sme to spravili s prvou stránkou.
<Logger File>
Global
FileName output-main.txt
Level debug
</Logger>
<Section>
Name main
#Set variable name $url (loaded value from REQUEST - form input field search)
<Action Template>
TemplateText $context->setVariable('$url', \
"http://www.prweb.com/cgi-bin/search/search.pl?Terms=" . $_REQUEST['search'] . \
"&Match=0&Realm=prweb_inject&submit=Search");
</Action>
<Action ContentURL>
URL {$url}
</Action>
#process found resultset
<Action Eval>
File process_result_page.w
</Action>
#process also next pages of search result
<Section>
Name subpages
Optional
<Pattern>
RegExp Results Pages:
</Pattern>
#iterate through all next pages of search resultset
<Section While>
Name Next_Pages
EndAt [
#match pattern of next page link and load link into context variable $url
<Pattern>
RegExp <a href="{$url}">{$page_number}</a>
</Pattern>
#define URL in correct way, because in HTML it's not complete
<Action Template>
TemplateText $trans_tbl = get_html_translation_table(HTML_ENTITIES);\
$trans_tbl = array_flip($trans_tbl);\
$context->setVariable('$url', "http://www.prweb.com/cgi-bin/search/" . \
strtr($context->getVariable('$url'), $trans_tbl));
</Action>
#execute script, which process results as it was done with first page
<Action Eval>
File process_result_page.w
</Action>
</Section>
</Section>
</Section>
#start execution with section named: main
Main main