《搜索引擎零距离》第二章 IRS(2)

roki 2009-06-17
3.2.7  重试次数配置
由于网络传输的不稳定性,爬虫系统在访问Web页面时,有时由于暂时性的网络原因而导致访问失败,为了加强爬虫的访问能力,允许在访问页面失败后,多次尝试访问,因此爬虫配置中加入了这样的配置选项,比如:

---------------------------------------------	
入口 'http://abc.com/list.jsp?page=1'配置:重试次数=5,重试等待=1
---------------------------------------------


上述语句的意思是,在访问入口页面的时候,允许重试5次,每次重试之间等待1秒。
3.2.8  正则模式匹配语句
正则模式匹配语句描述了如何使用IEE表达式,借助正则表达式来提取页面中的结构化信息,比如:

--------------------------------------
	匹配:'bookinfo' '<a href="/book/[$]">[$bookName]</a><br/>'  '%bookEntrance'
-----------------------------------------


这是最简单的一条正则模式匹配语句,它的含义是,从页面中取出符合'<a href="/book/book/[$bookUrl]">[$bookName]</a><br/>' 这个模式的内容,并把相应位置的信息放入bookUrl和bookName这两个变量,并把所有匹配结果的列表命名为bookinfo,把匹配到的字符串中的URL地址部分命名为bookEntrance。如果页面内容如下的话:

-------------------------------------------------------------------
<a href="/book/url1">book1</a><br/>
<a href="/book/url2">book2</a><br/>
<a href="/book/url3">book3</a><br/>
-------------------------------------------------------------------

那么,通过变量%bookEntrance就可以引用到/book/url1、/book/url2和/book/url3这3个URL地址。引用URL地址的目的是为了进入次级的页面,继续抓取信息。而通过匹配名bookinfo,可以引用到book1、book2和book3这3个结构化数据。引用结构化数据的目的是为了持久化操作,比如存入数据库。
一条正则模式匹配语句由“匹配名声明”、“IEE表达式”、“匹配结果命名”、“匹配方式修饰语句”等几个部分组成。下面依次详细介绍。

3.2.9  匹配名声明
一个“正则模式匹配语句”是由关键字“匹配”开头的句子,在“匹配”这个关键字后,可以加上这个“正则模式匹配语句”的名字,比如,“匹配:bookinfo”,也可以不起名字,就只是“匹配”这两个汉字。
3.2.10  IEE表达式
IEE表达式是如何从页面内容中提取结构化信息的描述语句,在IRS语言中有3种类型的IEE表达式。
1) 普通的以变量名来占据目标信息位置的形式
比如上文中的

'<a href="/book/[$]">[$bookName]</a><br/>'

这个IEE语句的含义是匹配页面中符合 '<a href="/book/(.*?)">(.*?)</a><br/>'这个正则表达式的内容,并且把在第二个非贪婪匹配的位置匹配到的文本放入名叫$bookName的变量中去。单个的[$]表示这个位置上的信息不需要保存。
事实上,系统会把IEE表达式转化为对应的正则表达式去匹配文本,并利用Java语言的java.util.regex库中的函数来提取出目标位置的信息,再把找到的信息放入一个数组。
假设目标文本是:

'<a href="/book/url1">book1</a><br/>'
'<a href="/book/ url2">book2</a><br/>'

那么,IEE表达式的处理结果就是这样:

result=[ {'bookName'=>'book1'}, {'bookName'=>'book2'}]
附注: 这里使用 [ ] 来表示数组, 用{} 来表示映射表。

上述的处理结果是一个数组,而数组里的元素是两个映射表, 映射表中的键bookName对应值是book1和book2。系统使用了这样的数据结构来存储结构化信息采集的临时结果。
2) 直接写正则表达式的扩展形式
比如:

'<a href="/book/\d+">[$bookName]</a><br/>'


这个式子中的\d+的意思是,匹配一个或多个数字,这个式子与之前的[$]相比,多了一些限制。也就是说,只有‘<a href="/book/111">book1</a><br/>’这样的内容才能匹配,而‘<a href="/book/aaa">book1</a><br/>’就不匹配了,因为aaa不是数字。这个模式要生效的话,需要按照下面的形式加上一个修饰符“#模式=正则”:

--------------------------
匹配:'bookinfo' '<a href="/book/\d+">[$bookName]</a><br/>'  '%bookEntrance,#模式=正则'
-------------------------


3) 组匹配模式
“组匹配模式”是为了能够方便地匹配一组相同格式的数据而引入的模式。前面已经提到过“组匹配”的概念:

--------------------------------------------------
匹配:'film'	'电影名:[$fileName]主演:[%actorInfo=<a href="[$url]>[$actor]</a>%]...更多'
'#组模式{& \s};'
---------------------------------------------------


这句“正则模式匹配语句”可以从以下文本中提取出所需的结构化信息,提取结果如表3.1所示。


-------------------------------------------------------------------
电影名:黄金甲
主演: <a href=" zhoujielun.htm">周杰伦</a><a href="zhourunfa.htm">周润发</a><a href="gongli.htm">巩俐</a> ...更多

电影名:色戒
主演: <a href="liangchaowei.htm">梁朝伟</a><a href="tangwei.htm">汤唯</a> ...更多
-------------------------------------------------------------------

表3.1  提取结果
fileName actorInfo
黄金甲 zhoujielun.htm&周杰伦  zhourunfa.htm&周润发 gongli.htm&巩俐
色戒 liangchaowei.htm&梁朝伟 tangwei.htm&汤唯


3.2.11  模式匹配修饰符
模式匹配修饰符有多种作用,下面分别介绍。
1.匹配次数范围限制修饰符
有些情况下,对于某个IEE表达式,我们只希望匹配指定的次数而不是全部匹配。比如上文中的

'<a href="/book/url1">book1</a><br/>'
'<a href="/book/url2">book2</a><br/>'
'<a href="/book/url3">book3</a><br/>'
'<a href="/book/url4">book4</a><br/>'

正文中有3条符合 '<a href="/book/[$]">[$bookName]</a><br/>' 这个模式的,但是可能我们只需要其中的两条。对于这样的需求,可以使用“匹配次数范围限制修饰符”。用法如下:
--------------------------
	匹配:'bookinfo' '<a href="/book/[$]+">[$bookName]</a><br/>'  
	'%bookEntrance,#最多匹配{2}'
-------------------------


如果需要匹配4条记录中的第2~4条,可以这样写:

--------------------------
	匹配:'bookinfo' '<a href="/book/[$]+">[$bookName]</a><br/>'  
	'%bookEntrance,#匹配范围{2..4}'
-------------------------


另外的写法,比如{1,3..}的意思是匹配第1条和第3条,以及第3条之后所有记录。
2.POST地址拼接语句
存在这样一种情况:
假设我们使用“正则模式匹配表达式”

--------------------------
匹配:'bookinfo' '<a href="/book/[$url]+">[$bookName]</a><br/>' 
'%bookEntrance, '
-------------------------

这段IEE表达式从页面内容

------------------------------------------
'<a href="/book/url1">book1</a><br/>'
'<a href="/book/url2">book2</a><br/>'
-----------------------------------------

中分析得到的结果集数组中的url字段的值分别是url1和url2。爬虫再根据这次匹配结果进入次一级的页面的时候,将使用/book/url1和book/url2这两个地址。但是如果我们想让爬虫进入的不是这两个地址,而是其他的地址,则可以使用“POST地址拼接语句”来实现。
如果“正则模式匹配表达式”写成

-------------------------------------------------------------------
	匹配:'bookinfo' '<a href="/book/[$url]+">[$bookName]</a><br/>'  
	'%bookEntrance, #post->http://abc.com/other/$url'
-------------------------------------------------------------------


的话,则爬虫将把匹配到的$url变量的值url1和url2代入http://abc.com/other/$url,于是爬虫可以进入的次级页面的地址就变成http://abc.com/other/url1和http://abc.com/other/url2。这个修饰语句的主要作用是,从可以匹配到的结构化数据中取出可以拼接成目标次级URL地址的数据,并按照指定格式生成目标次级URL,供爬虫进一步采集数据。
3.地址扩展修饰语句
地址扩展修饰语句适用在如下情况下。
假设页面内容如下:

-----------------------------
总页数12页
----------------------------

在使用IEE表达式“总页数[$pageNum]页”提取得到数据pageNum=12之后,如果希望爬虫能进入

http://abc.com/otherpage?page=1
http://abc.com/otherpage?page=2
……
http://abc.com/otherpage?page=12


这些页面的时候,可以这样写:

-----------------------------
匹配:'page' '总页数[$pageNum]页' 
'#extend->http://abc.com/otherpage?page=[1..$pagNum]'
----------------------------

这个语句可以利用页面中提取到的结构化信息来构造爬虫将要进入的次级页面。在地址扩展语句中,还可以加入在其他模式匹配语句中匹配到的变量,具体的功能用法将在本章末尾结合实例来阐述。
4.HREF提取修饰语句
存在这样一种情况,用IEE表达式匹配到的文本内容中,存在多于一个的URL地址,比如,页面内容:

------------------
<td><a href="url1.jsp">abc</a><a href="targurl.jsp">target</a></td>
----------------

正则模式匹配语句:

------------------
匹配 '<td><a href=[$] <a href="[$targetUrl]">target</a></td>' '%entrance'
------------------

用以上匹配语句可以从页面中匹配出目标URL所要的文本段,但是如何标识出爬虫应该是进入第1个URL url1.jsp,还是第2个URLtargurl.jsp?
在IRS中可以使用HREF提取修饰语句来表达这样的需求,示例如下:
------------------
匹配 '<td><a href=[$] <a href="[$targetUrl]">target</a></td>' 
'%entrance,#href{$targetUrl }'
------------------


上述语句中#href{$targetUrl }这一段,可以使得爬虫能够进入保存在$targetUrl变量中的URL地址,而不是默认的第一个地址url1.jsp。次级页面语句如下:
------------------------------------------------------
次级 页内 '%entrance{targetUrl }' '页面名'
------------------------------------------------------

5.组匹配模式修饰语句
为了方便地把一组格式相同的结构化数据以一定格式保存下来,引入了这个修饰语句,本语句的主要特性已经在“组匹配模式”中介绍过。
页面内容,参见组匹配模式中的页面IRS:

------------------------------------------------
匹配:'film'  '电影名:[$fileName]主演:[%actorInfo=<a href="[$url]>[$actor]</a>%]...更多'
'#组模式{& \s};'
---------------------------------------------------


匹配结果见表3.2所示。
表3.2  匹配结果
fileName actorInfo
黄金甲 zhoujielun.htm&周杰伦  zhourunfa.htm&周润发 gongli.htm&巩俐
色戒 liangchaowei.htm&梁朝伟  tangwei.htm&汤唯


3.2.12  节点模式匹配语句
节点模式匹配与正则模式匹配的主要区别在于,前者可以指定,匹配过程只针对页面的DOM树上的某一个或多个节点上的文本,而不是后者所对应的全部文本,节点模式匹配的主要特性已经在上文的“树节点直接标识方法”中有过比较详细的描述。
IRS脚本代码示例如下:

-------------------------------------------------------------------
节点:'gt' 0.3.16.1.1.1.5 'target="_blank">[$name]</a>'  'NULL'
-------------------------------------------------------------------

上述代码表示:提取页面DOM树上位于 0.3.16.1.1.1.5 位置上符合'target="_blank">[$name]</a>' 模式的信息,后面跟的NULL表明没有额外的修饰语句(所有在上节中提到的模式匹配修饰符都可以用在节点模式匹配语句中)。
一个额外的特性是,节点路径上可以加通配符*,比如 3.*.1,表示所有3.1.1, 3.2.1,3.3.1……这些路径上的节点都在本条“节点模式匹配语句”的处理范围之内。
Global site tag (gtag.js) - Google Analytics