在上一节中介绍了一些基本的采集思路,上一节中涉及到的正则表达式并不保证长期有效,一旦阿里巴巴页面改版,规则就有可能失效,到时就需要重新调整规则。 这一节就介绍一下采集的主要脚本模式...

    在上一节中介绍了一些基本的采集思路,上一节中涉及到的正则表达式并不保证长期有效,一旦阿里巴巴页面改版,规则就有可能失效,到时就需要重新调整规则。 这一节就介绍一下采集的主要脚本模式:三层循环(上一节提到是双循环,其实应该是三层循环,第一层是关键词的循环层,第二层是分页链接的循环层,第三层是 每页的内容链接的循环层)。

    这一节就用原装的"资讯模块规则.zl"来进行说明,下面是该脚本的代码片段:

.................................  //省略N行源代码

keywords_count = bltGetKeyWords(keywords,mustwords); //首先得到关键词信息,前面的章节提到过

if(keywords_count > 0) //如果有关键词则执行采集循环

    for(i=0;i<keywords_count && caiji_totalcount < Max_CaijiNum;i++) //第一层对关键词循环,同时如果caiji_totalcount当前的采集量已经超过需要的量时也停止循环

    .................................  //省略N行源代码

        for(pageindex = 0 ;pageindex < pagecount && caiji_totalcount < Max_CaijiNum; pageindex++) //第二层对采集分页进行循环

        .................................  //省略N行源代码

            for(contentIndex = 0 ; contentIndex < contentCount && caiji_totalcount < Max_CaijiNum; contentIndex++) //第三层对采集分页中的内容链接进行循环
                if(myCheckContentLinkExists()) //自定义函数,用于判断内容链接在本地数据库中是否存在,如果已经存在则continue跳过该链接。
                    continue;
                endif
                .................................  //省略N行源代码

                myInsertToDb(); //自定义函数,将当前内容链接捕获到的信息如采集标题,采集内容等插入到本地数据库中。

            endfor //第三层循环结束标识符
       
        endfor //第二层循环结束标识符
   
    endfor  //第一层循环结束标识符

elif(keywords_count == 0)
    printf('分类的关键词为空\n',RED);
else
    printf('获取分类的关键词时发生错误\n',RED);
endif
   
    上面就是三层循环的基本架构,其他的供应,商城,团购等模块的采集规则脚本都是按照这个架构来做的,只是这些模块采集的字段和规则都比资讯的多很多,资讯就两个采集字段:标题和内容。

    这里来看下上面看的到两个自定义函数:myCheckContentLinkExistsmyInsertToDbmyCheckContentLinkExists函数的代码如下:

fun myCheckContentLinkExists()

    global content_links,contentIndex,catid; //在自定义函数里如果需要使用全局变量,就需要通过global关键字来引用

    if(bltSqlTableExists('article')) //bltSqlTableExists内建函数用于判断该网站对应的sqlite本地数据库中是否存在article表,资讯的采集数据都存放在article表中。

        sql = "SELECT * FROM article WHERE linkurl='"+bltSqlEscape(content_links[contentIndex])+"' AND catid='"+catid+"'"; //将要执行的sql数据库查询语句。这条语句的意思是从article表中查找linkurl字段等于当前采集内容链接的记录,如果找到则说明该链接已 经采集过了。bltSqlEscape内建函数用于对查询的内容链接进行转义,转义后的字符串才能进行安全的数据库查询操作。

        if(!bltSqlQuery(sql)) //bltSqlQuery内建函数用于执行数据库的查询语句。

            bltExit('查询'+sql+'失败'); //bltExit内建函数用于出错时直接退出本脚本。

        elif(bltSqlMoveToNext()) //bltSqlMoveToNext内建函数将查询的结果集里的游标向下移一行,只有这样才能指向真正的查询结果。

            print bltSqlGetString('linkurl') + '["' + bltSqlGetString('title') + ']"采集地址已经存在!';

            bltSqlRelease();

            return TRUE; //返回TRUE,前面提到过TRUE是数字1的宏。

        endif

        bltSqlRelease(); //手动立即释放数据库查询时占用的资源,当然不手动释放也没事,因为系统会在后面适当的时候自动释放,不过由于系统不会立即自动释放资源,所以手动释放要好点。

        return FALSE; //不存在,则返回FALSE,即数字0的宏

    else

        bltSqlExec('CREATE TABLE article (id INTEGER PRIMARY KEY ASC,catid,title,content,state,linkurl)'); //bltSqlExec内建函数用于执行各种数据库的创建,插入,更新操作。

        print '创建article资讯数据表!';

        return FALSE;

    endif

endfun

    上面的函数涉及到了数据库的基本操作,如查询,创建表等操作,bltSqlQuery主要用于查询方面的读取数据库的操作,而bltSqlExec则主要用于创建,插入,更新等对数据库进行写入的操作。

    下面看下myInsertToDb函数,该函数将采集到的数据插入到相应的数据库表结构中:

fun myInsertToDb()
    global catname,catid,title,content,content_links,contentIndex,caiji_totalcount; //通过global引用函数外的全局变量,如title采集到的标题,content采集到的内容等

    sql = "INSERT INTO article (catid,title,content,state,linkurl) VALUES ('" + catid + "','" +
                bltSqlEscape(title) + "','" +
                bltSqlEscape(content) + "','0','" +
                bltSqlEscape(content_links[contentIndex]) + "')";
//将title标题,content内容,content_links[contentIndex]当前采集的内容链接地址等经过bltSqlEscape内建函数转义后插入到article表结构中。

    if(!bltSqlExec(sql)) //通过bltSqlExec来执行数据库的插入操作。
        bltExit('执行'+sql+'失败');
    endif

    caiji_totalcount++; //将当前分类的采集总量加一。
    bltAddProgress(1); //通过bltAddProgress增加采集器底部进度条的进度。
    printf('采集(' + title + ')到本地数据库的['+catname+']分类中\n',GREEN);
endfun


    上面是采集数据的入库操作,下面看下和发布有关的函数myPostDataToWeb

fun myPostDataToWeb()

.................................  //省略N行源代码

    sql = "SELECT * FROM article WHERE catid='" + catid + "' AND state='0'"; //先从article表中查询所有state为0的采集信息,state为0的都是采集上来还没发布的数据,state为1的为发布过的,或者被过滤掉的数据

    if(!bltSqlQuery(sql)) //通过bltSqlQuery执行查询操作
        bltExit('查询'+sql+'失败');
    endif

    .................................  //省略N行源代码
   
    for(;bltSqlMoveToNext();bltAddProgressEx(RowCount,totalRowCount)) //循环将采集的数据进行上传发布。

   
.................................  //省略N行源代码

    printf('发布中...',GREEN);
    ret = bltPostData(url,array('moduleid',bltIntToStr(modid,0,'0'),
                                              'file','index',

                                             ........ , ........),&output); //bltPostData 向url指向的网址发送post请求,第二个参数为一个数组,该数组每两项构成一个名值对,该数组包含了采集的标题,内容等,通过bltPostData 将这些采集的数据上传发布到服务器中,最后一个参数是一个变量引用,如&output,在bltPostData将数据上传到服务端后,服务端返 回的数据就会存放在output变量中,从output变量值中就可以判断发布是否成功。如果发布失败,失败的原因也可以从output中得到。

    .................................  //省略N行源代码

   
endfor

endfun

    上面就是采集脚本的采集和发布的基本结构,最后在看下两个内建函数:bltCheckUserPausebltTellSysCaijiStatusbltCheckUserPause内建函数会判断用户是否需要在采集结束时的提示服务,如果需要,则暂停系统,然后在右下角弹出气泡提醒用户采集结束,此时可以对采集数据进行处理,处理完后再发布,bltTellSysCaijiStatus内建函数则用于告诉采集器当前分类的采集总量和发布成功的数量,这样在所有采集结束后,采集器才能统计出正确的采集总量和发布成功的总量信息。

    下一节将对本采集器所涉及的所有内建函数进行列举和说明(本节中有些内建函数如bltRegexReplace等都将在后面的章节中进行列举和说明)。

    OK,先到这里,休息,休息一下,O(∩_∩)O~

上下篇

下一篇: zengl脚本语法 第六章内建函数枚举

上一篇: zengl脚本语法 第四章采集入门篇

相关文章

zengl脚本语法 第一章入门篇

zengl脚本语法 第三章函数篇

智能采集器 v1.2.0 公测版

智能采集器v1.0.3

智能采集器v1.0.4

智能采集器v1.0.0 安装使用教程