在上一节中介绍了一些基本的采集思路,上一节中涉及到的正则表达式并不保证长期有效,一旦阿里巴巴页面改版,规则就有可能失效,到时就需要重新调整规则。 这一节就介绍一下采集的主要脚本模式...
在上一节中介绍了一些基本的采集思路,上一节中涉及到的正则表达式并不保证长期有效,一旦阿里巴巴页面改版,规则就有可能失效,到时就需要重新调整规则。 这一节就介绍一下采集的主要脚本模式:三层循环(上一节提到是双循环,其实应该是三层循环,第一层是关键词的循环层,第二层是分页链接的循环层,第三层是 每页的内容链接的循环层)。
这一节就用原装的"资讯模块规则.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
上面就是三层循环的基本架构,其他的供应,商城,团购等模块的采集规则脚本都是按照这个架构来做的,只是这些模块采集的字段和规则都比资讯的多很多,资讯就两个采集字段:标题和内容。
这里来看下上面看的到两个自定义函数:myCheckContentLinkExists和myInsertToDb。myCheckContentLinkExists函数的代码如下:
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
上面就是采集脚本的采集和发布的基本结构,最后在看下两个内建函数:bltCheckUserPause和bltTellSysCaijiStatus,bltCheckUserPause内建函数会判断用户是否需要在采集结束时的提示服务,如果需要,则暂停系统,然后在右下角弹出气泡提醒用户采集结束,此时可以对采集数据进行处理,处理完后再发布,bltTellSysCaijiStatus内建函数则用于告诉采集器当前分类的采集总量和发布成功的数量,这样在所有采集结束后,采集器才能统计出正确的采集总量和发布成功的总量信息。
下一节将对本采集器所涉及的所有内建函数进行列举和说明(本节中有些内建函数如bltRegexReplace等都将在后面的章节中进行列举和说明)。
OK,先到这里,休息,休息一下,O(∩_∩)O~