我正在开发视频播放器,用于扫描用户的视频文件并尝试从文件名中识别它们。如果视频是电影,我想得到它的名字和视频的质量,如果是电视节目,我想得到节目的名称,季节的号码,剧集的号码和视频的质量。
我用Google搜索了一些示例文件名,并制作了一个简单的脚本,试图获取信息,但是我很难处理异常,例如在质量之前有剧集的名称,当文件的标签像“PROPER”或者如果用户在质量之前将视频的来源设置为“BluRay”。
如果有更熟练使用正则表达式的人会给予一些帮助,我将非常感激。
谢谢!
import re
names = [
"The.Newsroom.2012.S02E06.720p.HDTV.x264-KILLERS.mkv",
"Breaking.Bad.S05E10.Buried.HDTV.XviD-AFG.avi",
"Breaking.Bad.S05E10.Buried.720p.HDTV.x264-AFG.mkv", #Incorrectly nonHD
"Dexter.S08E08.HDTV.XviD-AFG.avi",
"Dexter.S08E07.1080p.HDTV.x264-QCF.mkv",
"Dexter S08E07 720p HDTV x264-QCF.mkv",
"The.Great.Gatsby.2013.BluRay.1080p.DTS.x264-CHD.mkv", #Incorrectly nonHD
"The Forbidden Girl 2013 BRRIP Xvid AC3-BHRG.avi",
"Pain.&.Gain.2013.720p.BluRay.DD5.1.x264-HiDt.mkv",
"Band.of.Brothers.S01E02.Day.of.Days.DVDRip.XviD-AC3-BAGS.avi",
"Dexter.S08E06.PROPER.720p.HDTV.x264-IMMERSE.mkv", #Incorrectly nonHD
"Dexter S08E06 PROPER 720p HDTV x264-IMMERSE.mkv" #Incorrectly nonHD
]
for name in names:
tv = re.findall(r"(.*?)[ |.]S([\d+]{1,2})E([\d+]{1,2})[ |.]([\d+]{3,4}p|)", name) #FIXME: Get quality also after "PROPER/EPTITLE/.."
if len(tv)>0:
print("---------- TV ----------")
print("Show: "+tv[0][0].replace(".", " "))
print("Season: "+str(int(tv[0][1])))
print("Episode: "+str(int(tv[0][2])))
print("Quality: "+(tv[0][3] if len(tv[0][3])>0 else "nonHD"))
else:
movie = re.findall(r"(.*?[ |.][\d+]{4})[ |.]([\d+]{3,4}p|)", name) #FIXME: Get quality also after "BluRay/HDTV/HDDVD/.."
if len(movie)>0:
print("--------- MOVIE --------")
print("Title: "+movie[0][0].replace(".", " "))
print("Quality: "+(movie[0][1] if len(movie[0][1])>0 else "nonHD"))
else:
print("error")
答案 0 :(得分:2)
正如Josh所说,+
限定符不应与{m,n}
一起使用。 +
匹配一个或多个re {m,n}
匹配m到n重复贪婪。 (见:re syntax)。
他也很高兴使用re.VERBOSE来帮助您了解正则表达式的可读性。
编辑:(感谢@eyguem指出这一点)我可能错了,但你的[ |.]
试图匹配一个空格和一个句号?如果是这样,你不需要|
,这可能是逃避 .
等特殊字符的好习惯。 (即[ \.]
)。
如果你知道季节/剧集和质量之间的字符串是字母,空格或句号,你可以使用这样的字母(编辑:如果有非字母字符,如' - ','+'等,你'我需要将它们添加到字符集中):
tv = re.findall(r"""(.*) # Title
[ .]
S(\d{1,2}) # Season
E(\d{1,2}) # Episode
[ .a-zA-Z]* # Space, period, or words like PROPER/Buried
(\d{3,4}p)? # Quality
""", name, re.VERBOSE)
同样,您可以为电影部分执行此操作:
movie = re.findall(r"""(.*?[ .]\d{4}) # Title including year
[ .a-zA-Z]* # Space, period, or words
(\d{3,4}p)? # Quality
""", name, re.VERBOSE)
这是输出:
---------- TV ----------
Show: The Newsroom 2012
Season: 2
Episode: 6
Quality: 720p
---------- TV ----------
Show: Breaking Bad
Season: 5
Episode: 10
Quality: nonHD
---------- TV ----------
Show: Breaking Bad
Season: 5
Episode: 10
Quality: 720p
---------- TV ----------
Show: Dexter
Season: 8
Episode: 8
Quality: nonHD
---------- TV ----------
Show: Dexter
Season: 8
Episode: 7
Quality: 1080p
---------- TV ----------
Show: Dexter
Season: 8
Episode: 7
Quality: 720p
--------- MOVIE --------
Title: The Great Gatsby 2013
Quality: 1080p
--------- MOVIE --------
Title: The Forbidden Girl 2013
Quality: nonHD
--------- MOVIE --------
Title: Pain & Gain 2013
Quality: 720p
---------- TV ----------
Show: Band of Brothers
Season: 1
Episode: 2
Quality: nonHD
---------- TV ----------
Show: Dexter
Season: 8
Episode: 6
Quality: 720p
---------- TV ----------
Show: Dexter
Season: 8
Episode: 6
Quality: 720p
答案 1 :(得分:1)
如果使用re.VERBOSE标志打破了正则表达式,可能会有所帮助。
我看到了
[\d+]{3,4}
我认为这是误导。这是不是意味着“三次或四次重复至少一个小数”?我想
\d{3,4}
很好。
在开发正则表达式时,我首先要创建小模式:
episode_pattern = re.compile(r"S\d+E\d+", re.IGNORECASE)
希望有所帮助。
答案 2 :(得分:1)
[ae*6]
代表一个角色。这意味着此字符可以是a
,e
,*
或6
。
然后,没有必要写[ |.]
,顺便说一下,“字符为,
|
或.
”。
我做了一些改进。如果您有任何疑问,请不要犹豫,问我。
注意:像{1}}这样的部分:(?:[ .](\d{3}\d?p)|\Z)
有必要强制懒点.*?
转到下一个点。,然后是 720p (如果有),不要停在第一个点。并考虑数字和 p 是可选的
如果没有这样的 720p ,那么懒字点会一直持续到字符串的末尾(.*?
强制它这样做)并声明它没有找到任何 720p 强>
\Z
答案 3 :(得分:0)
我知道这个问题用“re module”来说,但为了有用而不是迂腐,这里有一个更简单,更快速的文件名解析。
file_name = path.rsplit('.', 1)[0].rsplit('/', 1)[-1]
如果你需要它同时适用于windows和unix,最后添加一个rsplit('\',1)[ - 1]。这是快速,可预测的,并且每次都会解析文件名。