扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
作者:builder.com.cn 2007年1月17日
关键字:
使用正规式查找信息
假设我们已经有了需要处理的Web页面的文本内容,现在我们要做的就是查找其中所有的图片标签。可能有些人没有注意到,事实上,在HTML文档中,页面中的图片是以类似如下的方式进行编码的(添加或者删除一些属性):
<img src="/path/to/image.png">
我们真正感兴趣的是引号中的内容,其它的部分可以忽略。我们将使用简单正规式和findall函数来完成复杂的工作。正规式是一种规定标识符串语法规则的方法(在这里,标识符指的是字符、数字、字母或者标点符号),所有种类的字符串都可以被识别,而不需要分别指定。关于正规式有专门的文章讨论,这里我们只看几个例子:
假设你有一些文本数据,并且需要识别其中的二进制字符串,也就是只由0和1组成的字符串。对应的正规式如下所示:
(0|1)+
圆括号用来将多个字母进行组合,中间的竖线("|")意味着选择,既可以匹配竖线左边的字符,也可以匹配竖线右边的字符。最后,"+"表示“要和前面的标识符至少匹配一次或者多次”。所以这一正规式匹配的字符应该是“一个或者多个重复的 0或者1”。对于正规式来说,我们还需要掌握一些常用的标号。例如,句点(".")代表任意的单个字符,星号"*"的用法和"+"类似,但是"*"表示匹配的次数是零次或者多次。所以,一个数目多于5的任意字符串的正规式是下面的形式:
......*
对于编写正规式来识别html中的图像来说,我们的知识已经足够了。为了运行表达式,我们需要使用函数sre.findall,函数的返回值是包含字符串中所有匹配组的列表。下面的代码就完成查找图片的功能:
matches = sre.findall('<img .*src="?(.*?)"?', website_text)
这里有几个问题需要注意:首先,我们将字符串放入单引号中,将它作为路径的起始和结束标记,因为我们还希望在字符串中能够使用双引号。其次,我们使用符号'(', ')'将我们感兴趣的内容组合起来, findall函数将会自动丢弃所有不在组合中的部分。最后,我们使用"?"来完成两项工作。如果"?"紧跟在表达式之后,则匹配0个或1个由前面的正则表达式定义的片段,如果"?"是紧跟在"*"之后,则意味表达式匹配置处于‘非贪婪’模式。默认情况下,正规式匹配是贪心的,也就是说,它会匹配尽可能多的文本内容,我们想做的正好相反,只匹配到第一个"被找到。如果我们现在打开了页面http://www.builderau.com.au并且运行了正规式,我们会得到下面的结果(你们的结果可能不同,这取决于首页的图片内容):
['http://ad.au.doubleclick.net/ad/popup.builderau.com.au/;sz=1x1;ord=123456789?',
'/i/s/cov/checklist170110.jpg', '/i/s/cov/perl170110.jpg', '/i/s/cov/atwork170110.jpg',
'/i/x/blogs/brendon_chase_52x52.gif', '/i/x/blogs/chris_duckett_52x52.gif',
'http://dw-eu.com.com/clear/c.gif?ts=1163740722&sId=75']
到了这一步,我们又遇到了新问题:Web页面中的图片路径既可以表示成绝对路径也可以表示成与页面的相对路径两种形式。从上面的数据中,我们就可以看到这点,一些图片是全路径的形式,并以"http:// "起始,而另外一些只含有目录名。我们的程序应该能够在相对链接的开始添加当前页面的路径。首先,我们需要得到当前页面的路径,我们之前已经完成了很多工作,这里就可以调用urllib2来确定当前的站点地址:
dir = website_handle.geturl().rsplit('/',1)[0]
if (dir == "http:/"):
dir = website_handle.geturl()
我们使用字符串函数rsplit移除页面自身的文件名。rsplit和其兄弟函数split可以按照某个特定的字符对字符串分段,例如:
>>> "Hello World".split(' ')
['Hello', 'World']
>>> "Hello World".rsplit('l')
['He', '', 'o Wor', 'd']
>>> "Hello World".split('l',1)
['He', 'lo World']
>>> "Hello World".rsplit('l', 1)
['Hello Wor', 'd']
唯一性和排序
我们已经得到了所有有效的图片链接,下面要做的就是将结果以最好的方式输出。在这个例子中,我们要删除结果中的重复数据,并对结果进行排序。在Python语言中,使得结果唯一的最简单方式就是将数据存储在一个容器中,例如set。Set类型和List类型很相似,它们之间的区别在于Set中的数据必须是唯一的并且并不是按照特定的顺序存储。这里我们只使用set的基本特性:
>>> x = ['set', 'contents', 'hello', 'world']
>>> y = set(x)
>>> y
set(['world', 'set', 'hello', 'contents'])
>>> y.add("new item")
>>> y
set(['new item', 'world', 'set', 'hello', 'contents'])
>>> list(y)
['new item', 'world', 'set', 'hello', 'contents']
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者