在Python regex中进行通配符字符串匹配
我想写一些简单的代码来下载一个Facebook页面的“粉丝”数量。
但是,不知道为什么,尽管我尝试了很多次,我还是无法让下面的代码从HTML中提取出粉丝数量。我在网上找到的其他解决方案也没有正确匹配这个情况的正则表达式。难道在这两个匹配的部分之间不可以有一些通配符吗?
我想匹配的文本是“6 of X fans”,其中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 个回答
不需要正则表达式
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
Evan Fosmark已经给出了一个很好的答案。这只是更多的信息。
你有这一行:
pattern = "6 of(.*)fans"
一般来说,这个正则表达式并不好。如果输入的文本是:
"6 of 99 fans in the whole galaxy of fans"
那么匹配的部分(括号里的内容)会是:
" 99 fans in the whole galaxy of "
所以,我们想要一个模式,能够准确抓取你想要的内容,即使输入文本像上面那样搞笑。
在这种情况下,匹配空格并不重要,因为当你把字符串转换为整数时,空格会被忽略。但我们还是写一个模式来忽略空格。
使用*
这个通配符,可以匹配长度为零的字符串。在这种情况下,我认为你总是想要一个非空的匹配,所以你应该使用+
来匹配一个或多个字符。
Python有非贪婪匹配的功能,所以你可以用这个来重写。不过,旧的正则表达式程序可能没有非贪婪匹配,所以我也会给出一个不需要非贪婪的模式。
所以,非贪婪的模式是:
pattern = "6 of\s+(.+?)\s+fans"
另一个是:
pattern = "6 of\s+(\S+)\s+fans"
\s
表示“任何空白字符”,可以匹配空格、制表符和其他一些字符(比如“换页符”)。\S
表示“任何非空白字符”,匹配任何\s
不会匹配的东西。
第一个模式在处理搞笑的输入文本时表现得比你最初的模式要好:
"6 of 99 fans in the whole galaxy of fans"
它会返回一个匹配组,仅仅是99
。
但试试这个搞笑的输入文本:
"6 of 99 crazed fans"
它会返回一个匹配组99 crazed
。
第二个模式根本不会匹配,因为“crazed”这个词不是“fans”。
嗯,这里有一个最后的模式,即使在搞笑的输入文本中也应该总是能正确工作:
pattern = "6 of\D*?(\d+)\D*?fans"
\d
匹配任何数字('0'
到'9'
)。\D
匹配任何非数字。
这将成功匹配任何不太模糊的内容:
"6 of 99 fans in the whole galaxy of fans"
匹配组将是99
。
"6 of 99 crazed fans"
匹配组将是99
。
"6 of 99 41 fans"
它不会匹配,因为里面有第二个数字。
想了解更多关于Python正则表达式的内容,你可以阅读各种 网页 页面。如果你想快速回顾一下,在Python解释器中输入:
>>> import re
>>> help(re)
当你在“抓取”网页文本时,有时会遇到HTML代码。一般来说,正则表达式并不是处理HTML或XML标记的好工具(见这里);你可能更好地使用Beautiful Soup来解析HTML并提取文本,然后再用正则表达式抓取你真正想要的文本。
希望这些内容对你有趣或者有帮助。
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()
。因为 re.match()
是把模式和整个文档进行匹配,但实际上你只是想在文档中找一个片段。上面的代码会打印出:79,110
。当然,这个数字在其他人运行时可能会有所不同。