Web提取教程 - 从网站www.prweb.com上获取文章

在此教程中,我们将展示给您如何解决一个我们客户的问题。此客户的要求如下:

  1. 在网站search in http://www.prweb.com中为某一个关键词进行检索(例如:“black coffe”)。
  2. 所有被找到的PR文章都将被分析 - 不仅仅头十篇文章,而且包括所有检索结果页的文章(与“black coffe”有关的文章超过1600篇)。
  3. 每一篇PR文章都将被打开并存储到文件:{$year}-{$month}-{$id}.html

客户问我们,是否特定的任务可以通过Unit Miner完成。我们回到“可以完成”,因为我们开发Unit Miner就是为此目的。因此,让我们一起来使用Unit Miner来完成这个任务,请继续浏览我们的教程。

步骤 1 - 打开检索

第一步我们定义了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

在页面源代码处的主要文章被高亮显示:

步骤 2 - HTML 表单

在此步骤中,我将展示给您如何编写小的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();
}

?>

步骤 3 - 在网站www.prweb.com上执行搜索,并且抓去首页结果。

因此我们将返回到我们新的脚本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

步骤 4 - 抓取PR文章的urls

在之前的步骤中,我们想要执行脚本名为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 的意思是告诉系统使用标准的表达时区匹配文字。

.*? 是匹配每个字符的标准表达式,知道字符‘<’。

我们同时定义超过一个行为,标准打印输出匹配的文字。

步骤 5 - 抓取PR文章并存储到文件

现在我们接近任务完成。在这个步骤,我们将需要从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

向我说过的,我们已经准备好了。

是的,我们准备好了,但是我们忘了说明部分,我们不得不重复设置下面的页面结果。因此,我们来完成教程的最后一步。

步骤 6 - 重复申明所有结果页

我们必须在此编辑脚本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

© 2004-2012 QualityUnit.com, All rights reserved