在Python正则表达式搜索中匹配字符串的通配符

时间:2010-01-03 21:55:48

标签: python regex

我以为我会写一些快速代码来下载Facebook页面的“粉丝”数量。

出于某种原因,尽管我尝试了相当多的迭代次数,但我无法获得以下代码来挑选HTML中的粉丝数量。在这种情况下,我在网络上找到的其他解决方案都没有正确匹配正则表达式。当然可以在两个匹配位之间加一些通配符吗?

我想要匹配的文字是“ 6个X粉丝”,其中X是页面拥有的任意数量的粉丝 - 我想得到这个数字。

我正在考虑间歇性地轮询这些数据并写入文件,但我还没有解决这个问题。我也想知道这是否朝着正确的方向前进,因为代码看起来很笨重。 :)

import urllib
import re

fbhandle = urllib.urlopen('http://www.facebook.com/Microsoft')
pattern = "6 of(.*)fans" #this wild card doesnt appear to work?
compiled = re.compile(pattern)

for lines in fbhandle.readlines():
        ms = compiled.match(lines)
        print ms #debugging
        if ms: break
#ms.group()
print ms
fbhandle.close()

3 个答案:

答案 0 :(得分:11)

埃文福斯马克已经给出了一个很好的答案。这只是更多信息。

你有这一行:

pattern = "6 of(.*)fans"

一般来说,这不是一个好的正则表达式。如果输入文本是:

“整个银河系的99名粉丝中的6名”

然后匹配组(括号内的东西)将是:

“整个银河系的99名粉丝”

所以,我们想要一个只会抓住你想要的模式,即使是像上面那样愚蠢的输入文字。

在这种情况下,如果匹配空格并不重要,因为当您将字符串转换为整数时,将忽略空格。但是让我们写一下模式来忽略空格。

使用*通配符,可以匹配长度为零的字符串。在这种情况下,我认为您总是希望非空匹配,因此您希望使用+来匹配一个或多个字符。

Python可以使用非贪婪匹配,因此您可以使用它进行重写。具有正则表达式的旧程序可能没有非贪婪匹配,因此我还将提供一种不需要非贪婪的模式。

所以,非贪婪的模式:

pattern = "6 of\s+(.+?)\s+fans"

另一个:

pattern = "6 of\s+(\S+)\s+fans"

\s表示“任何空格”,并且会匹配空格,制表符和其他一些字符(例如“换页”)。 \S表示“任何非空白区域”,并匹配\s 匹配的任何内容。

第一种模式比使用愚蠢的输入文本的第一种模式更好:

“整个银河系的99名粉丝中的6名”

它将返回仅99的匹配组。

但是试试这个其他愚蠢的输入文字:

“99名狂热粉丝中的6人”

它将返回99 crazed的匹配组。

第二种模式根本不匹配,因为“疯狂”这个词不是“粉丝”这个词。

嗯。这是最后一个模式,即使使用愚蠢的输入文本也应该始终做正确的事情:

pattern = "6 of\D*?(\d+)\D*?fans"

\d匹配任何数字('0''9')。 \D匹配任何非数字。

这将成功匹配远程非模糊的任何内容:

“整个银河系的99名粉丝中的6名”

匹配组将为99

“99名狂热粉丝中的6人”

匹配组将为99

“99 41粉丝中的6”

它不会匹配,因为那里有第二个数字。

要了解有关Python正则表达式的更多信息,请阅读various web pages。要快速提醒,请在Python解释器中执行:

>>> import re
>>> help(re)

当您从网页“抓取”文本时,有时可能会违反HTML代码。通常,正则表达式不是忽视HTML或XML标记的好工具(参见here);您最好使用Beautiful Soup来解析HTML并提取文本,然后使用正则表达式来获取您真正想要的文本。

我希望这很有趣和/或有教育意义。

答案 1 :(得分:10)

import urllib
import re

fbhandle = urllib.urlopen('http://www.facebook.com/Microsoft')
pattern = "6 of(.*)fans" #this wild card doesnt appear to work?
compiled = re.compile(pattern)

ms = compiled.search(fbhandle.read())
print ms.group(1).strip()
fbhandle.close()

您需要使用re.search()代替。使用re.match()尝试将模式与整个文档进行匹配,但实际上您只是尝试匹配文档中的一个部分。上面的代码打印出来:79,110。当然,在其他人运行时,这可能是一个不同的数字。

答案 2 :(得分:0)

不需要正则表达式

import urllib
fbhandle = urllib.urlopen('http://www.facebook.com/Microsoft')
for line in fbhandle.readlines():
    line=line.rstrip().split("</span>")
    for item in line:
        if ">Fans<" in item:
            rind=item.rindex("<span>")
            print "-->",item[rind:].split()[2]

输出

$ ./python.py
--> 79,133