Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python正则表达式和IMDB Top 250列表_Python_Regex - Fatal编程技术网

Python正则表达式和IMDB Top 250列表

Python正则表达式和IMDB Top 250列表,python,regex,Python,Regex,我刚刚开始使用Python,我正在尝试将IMDB上的前250部电影与以下故障代码进行匹配: import urllib2 import re def main(): response = urllib2.urlopen('http://www.imdb.com/chart/top') html = response.read() entries = re.findall("/title/.*</font>", html) #Wrong regex p

我刚刚开始使用Python,我正在尝试将IMDB上的前250部电影与以下故障代码进行匹配:

import urllib2
import re

def main():
    response = urllib2.urlopen('http://www.imdb.com/chart/top')
    html = response.read()
    entries = re.findall("/title/.*</font>", html) #Wrong regex
    print entries

if __name__ == "__main__":
    main()

我的理由是,我希望匹配/title/和之间的所有内容,因此在这两者之间使用。*,但显然这不是正确的方法,因为它只是匹配整个列表,而不是每个条目。我对在线阅读的正则表达式教程感到非常困惑。。。。帮助?

您不应该使用正则表达式进行html解析。您应该使用专门的html解析器。 看看: 试试这个

def main(s):
    response = urllib2.urlopen('http://www.imdb.com/chart/top')
    html = response.read()
    entries = re.findall("<a.*?/title/(.*?)/\">(.*?)</a>", html) #Wrong regex
    return entries
它使用组作为imdb id和标题。条目将是一个元组列表

,因此,尝试使用正则表达式解析HTML对于处理HTML解析器构建的这类事情来说是一种糟糕的做法。python中有许多选项可用,如Beautiful Soup、lxml等

我将展示如何使用lxml和XPath表达式来获取所有前250个标题

import lxml
from lxml import etree
import urllib2

response = urllib2.urlopen('http://www.imdb.com/chart/top')
html = response.read()
imdb = etree.HTML(html)
titles = imdb.xpath('//div[@id="main"]/table//tr//a/text()')
如果您打印标题[0],它将输出“肖申克的救赎”。
对于XPath,可以使用firefox的firebug扩展或安装firepath

使用lxml和XPath进行简单操作:


这是一个很长的答案;我希望它既能满足你的需要,又能帮助你解释正则表达式的奥秘

实现这一点的方法是选择一个完整的单个条目,然后用与之匹配的模式替换要概括的部分

例如,您提到的页面中的第一个条目如下所示

<tr bgcolor="#e5e5e5" valign="top"><td align="right"><font face="Arial, Helvetica, sans-serif" size="-1"><b>1.</b></font></td><td align="center"><font face="Arial, Helvetica, sans-serif" size="-1">9.2</font></td><td><font face="Arial, Helvetica, sans-serif" size="-1"><a href="/title/tt0111161/">The Shawshank Redemption</a> (1994)</font></td><td align="right"><font face="Arial, Helvetica, sans-serif" size="-1">689,815</font></td></tr>
括号使|运算符只对表达式的一部分进行除法,而不是对所有部分进行除法。开头括号后的?:防止将插入式表达式作为一个组捕获,我们不希望这样,因为我们不关心特定电影的颜色。稍后将对此进行详细介绍

下一个因条目而异的问题是它是什么数字条目。我们将用以下内容替换条目的该部分:

\d{1,3}\。 每当您在正则表达式中看到反斜杠时,它都会做一些特殊的事情;它的作用取决于以下字符\d匹配任何十进制数字。{1,3}意味着它需要一到三个数字,因为所有条目号都在一到三位之间

反斜杠的另一个主要用途是字面上表示具有特殊功能的字符。点就是这样一个字符;它匹配任何字符。但这不是我们想要的;我们需要一个文字。。为了得到这个结果,我们使用\,它与。。需要使用的字符称为元字符,它们是:.^$*+?|{}[]\

最后,我们在数字周围加了括号。除了细分正则表达式外,括号还构成一个组;也就是说,它们表示您关心正则表达式的这一部分。使用re.findall时,仅保存组中的匹配部分;其他一切都被丢弃了。上面提到的?:用于不关心正则表达式的一部分,但需要使用括号来细分它的情况。我假设表中的所有信息,包括条目号,都是重要的信息,所以我将条目号括起来,但不包括下一个句号,我们不关心括号中的句号。如果你不在乎条目号,你可以去掉括号

之后是电影的配乐,我们处理的方式类似:

(\d\.\d)
接下来是电影的链接。这里唯一改变的是链接中的数字,它们总是七位数。因此,我们将用以下内容替换条目的该部分:

<a href="/title/tt(\d{7})/">
方括号表示它将匹配其中包含的任何字符。这些可以是文字字符,如标点符号、空格或字符范围,例如,A-Z匹配所有大写字母。范围由开头和结尾字符之间的连字符表示。末尾的连字符是文字连字符;它位于末尾,以免使正则表达式解析器误认为它是范围的一部分。请注意,大多数元字符不必在字符组中用反斜杠转义


同时,+表示重复前面的任何内容一次或多次。总而言之,每部电影的标题都由我选择的一个或多个角色组成。因为他试图解析一个特定的网页,而不是通用的HTML。正则表达式可以很好地用于他的目的。@Taymon:即使你试图解析一个特定的网页,你也应该使用html解析器——它们是用来做这些事情的——是的,这绝对是完美的。尝试使用codecs包解析Unicode字符:html=codecs.openresponse.read,r,utf-8,但似乎并不完全有效。可以将其简化为titles=imdb.xpath'//div[@id=main]/table//a/text'要使这更简单,请参阅:
(\d\.\d)
<a href="/title/tt(\d{7})/">
([^<]+)
entries = re.findall(r'<tr bgcolor="#(?:e5e5e5|ffffff)" valign="top"><td align="right"><font face="Arial, Helvetica, sans-serif" size="-1"><b>(\d{1,3})\.</b></font></td><td align="center"><font face="Arial, Helvetica, sans-serif" size="-1">(\d\.\d)</font></td><td><font face="Arial, Helvetica, sans-serif" size="-1"><a href="/title/tt(\d{7})/">([^<]+)</a> \((\d{4})\)</font></td><td align="right"><font face="Arial, Helvetica, sans-serif" size="-1">(\d{1,3}(?:,\d{3})*)</font></td></tr>', html)