在此教程中,我们将展示给您如何解决一个我们客户的问题。此客户的要求如下:
客户问我们,是否特定的任务可以通过Unit Miner完成。我们回到“可以完成”,因为我们开发Unit Miner就是为此目的。因此,让我们一起来使用Unit Miner来完成这个任务,请继续浏览我们的教程。
第一步我们定义了Logger标签,因为了解Unit Miner包含的内容是比较好的。同时,如果我们了解了Unit Miner,当我写任何新的代码或是发现代码中存在的问题时,我都可以使用Unit Miner。
在一个步骤中,我们将做一个比较小的主体框架,争取让每一个人都明白。因此,我们将建立名为main.w 的脚本。例如:在文件夹Wrapper/samples/prwe里面
#定义logger, 它将记录所有故障排除信息
<Logger File>
Global
#存储输出logger到文件
FileName output-debug.txt
Level debug
</Logger>
#主体
<Section>
Name main
</Section>
Main main
在页面源代码处的主要文章被高亮显示:
在此步骤中,我将展示给您如何编写小的HTML文档,在文档中将显示包含输入域的小型表单。同时,我将告诉您当有数据串被输入时,如何开始Unit Miner脚本。
因此,我们要在Wrapper/samples/prweb目录中建立index.php文件。如果目录不存在,那需要先建立目录。文件中将是HTML的主体部分,其打印小的表单和PHP部分。并执行UnitMiner脚本,名为main.w。
我们只想使用主要文章的标题和图片下方的短语。
正如我们所看到的,标题被Tag封装 <div class="cnnMainT1Hd"> … </div> 短语也在Tag封装里 <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();
}
?>
因此我们将返回到我们新的脚本main.w.
我们将增加到我们的空的框架命令,其将加载已提交的数据(域的值为“search”)。对于此目的,我们将使用标签<Action Template>, 它可以使我们执行任何PHP代码。在此标签中,我们将编写url,它可以用来在www.prweb.com中搜索。
下面的工作,我们将加载通过搜索返回的文章内容。为此,我们使用标签<Action ContentURL>。 同时,最后一步,我们将执行新的脚本(我们还没有的), 命名为"process_result_page.w".
此新脚本应该处理结果页面的所有内容 - 意味着抓取PR文章的urls。
每个脚本包括主体,其从指定的URL下载页面,然后在下载的内容里执行某些行为。我们将在下一步了解如何匹配这些数据。
<Logger File>
Global
FileName output-main.txt
Level debug
</Logger>
<Section>
Name main
#设计变量名称$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>
#开始执行主体,名称为: main
Main main
在之前的步骤中,我们想要执行脚本名为process_result_page.w的脚本。因此我们展示给您怎样准备此脚本。
请在同样的目录中建立名为process_result_page.w的文件,作为main.w。在脚本中,我们将加载结果页的内容(url被存在环境变量$url中)。我们将插入While cycle,它将通过所有被找到的样式集成在文档中。在Section While中,我们将插入标签Pattern, 它将在定义样式存在的内容中加载,并且加载匹配的变量值(PR文章的URLs)。最终,我们将执行下一个名为 "process_pr_page.w"的脚本,它将分开处理每一个详细页面。
为了匹配数据,我们必须指定匹配样式。下面的样式告诉系统去匹配在标签间的所有内容,<div class="cnnMainT1Hd"><h2><a*>...</a></h2></div>,并且存储匹配的值到变量$main_title中。
然后我们定义一个行为,此行为可以针对这个变量做一些工作。在我们的案例中,它只是使用Text命令标准打印输出结果。但是您可以保存值到文件,做一个数据库插入,或者使用此值加载或采集另外一个页面。
<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
在此,我们定义超过一个样式,它将匹配在<div class="cnnMainT1">...</div>间的内容,并且存储匹配的值到变量$short_text。
注意:我们在此变量后,使用特殊的修改器:re(.*?)。
:re 的意思是告诉系统使用标准的表达时区匹配文字。
.*? 是匹配每个字符的标准表达式,知道字符‘<’。
我们同时定义超过一个行为,标准打印输出匹配的文字。
现在我们接近任务完成。在这个步骤,我们将需要从PR文章写内容到指定的文件。因此,我们在同一个文件目录内建立一个名为 "process_pr_page.w"的文件。
在这个脚本中,我们将从在变量$link_url中加载与url匹配的内容。同时,我们将匹配PR文章数据(标题和文本)。并且,我们将保存内容到新的格式。
<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
向我说过的,我们已经准备好了。
是的,我们准备好了,但是我们忘了说明部分,我们不得不重复设置下面的页面结果。因此,我们来完成教程的最后一步。
我们必须在此编辑脚本main.w,因为在此脚本中我们加载了首页结果页。
在此脚本中,我们将匹配后面所有搜索页的urls,且完成首页后,用同样的脚本打开他们。
<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