如何安全地从URL获取文件扩展名?

时间:2011-01-23 22:15:37

标签: python file

考虑以下网址

http://m3u.com/tunein.m3u
http://asxsomeurl.com/listen.asx:8024
http://www.plssomeotherurl.com/station.pls?id=111
http://22.198.133.16:8024

确定文件扩展名(.m3u / .asx / .pls)的正确方法是什么?显然,最后一个没有文件扩展名。

编辑:我忘了提到m3u / asx / pls是音频流的播放列表(文本文件),必须进行不同的解析。目标确定扩展,然后将url发送到正确的解析函数。例如。


url = argv[1]
ext = GetExtension(url)
if ext == "pls":
  realurl = ParsePLS(url)
elif ext == "asx":
  realurl = ParseASX(url)
(etc.)
else:
  realurl = url
Play(realurl)
GetExtension()应该返回文件扩展名(如果有的话),最好不要连接到URL。

10 个答案:

答案 0 :(得分:36)

使用urlparse解析网址的路径,然后使用os.path.splitext获取扩展程序。

import urlparse, os

url = 'http://www.plssomeotherurl.com/station.pls?id=111'
path = urlparse.urlparse(url).path
ext = os.path.splitext(path)[1]

请注意,扩展名可能不是文件类型的可靠指示符。 HTTP Content-Type标头可能更好。

答案 1 :(得分:15)

这对于requestsmimetypes最简单:

import requests
import mimetypes

response = requests.get(url)
content_type = response.headers['content-type']
extension = mimetypes.guess_extension(content_type)

扩展名包含一个点前缀。例如,对于内容类型extension'.png''image/png'

答案 2 :(得分:11)

真正正确的方法是根本不使用文件扩展名。对相关URL执行GET(或HEAD)请求,并使用返回的“Content-type”HTTP标头获取内容类型。文件扩展名不可靠。

有关有用的MIME类型列表,请参阅Multimedia MIME reference

答案 3 :(得分:6)

文件扩展名在URL中基本没有意义。例如,如果您转到http://code.google.com/p/unladen-swallow/source/browse/branches/release-2009Q1-maint/Lib/psyco/support.py?r=292,您是否希望扩展名为“.py”,尽管页面是HTML而不是Python?

使用Content-Type标头确定网址的“类型”。

答案 4 :(得分:3)

$ python3
Python 3.1.2 (release31-maint, Sep 17 2010, 20:27:33) 
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from os.path import splitext
>>> from urllib.parse import urlparse 
>>> 
>>> urls = [
...     'http://m3u.com/tunein.m3u',
...     'http://asxsomeurl.com/listen.asx:8024',
...     'http://www.plssomeotherurl.com/station.pls?id=111',
...     'http://22.198.133.16:8024',
... ]
>>> 
>>> for url in urls:
...     path = urlparse(url).path
...     ext = splitext(path)[1]
...     print(ext)
... 
.m3u
.asx:8024
.pls

>>> 

答案 5 :(得分:2)

要获取内容类型,您可以编写一个类似于我使用urllib2编写的函数。 如果你需要利用页面内容,你很可能会使用urllib2,所以不需要导入操作系统。

import urllib2

def getContentType(pageUrl):
    page = urllib2.urlopen(pageUrl)
    pageHeaders = page.headers
    contentType = pageHeaders.getheader('content-type')
    return contentType

答案 6 :(得分:1)

除了URL的实际文件扩展名之外,不考虑其他因素的另一种方法:

def fileExt( url ):
    # compile regular expressions
    reQuery = re.compile( r'\?.*$', re.IGNORECASE )
    rePort = re.compile( r':[0-9]+', re.IGNORECASE )
    reExt = re.compile( r'(\.[A-Za-z0-9]+$)', re.IGNORECASE )

    # remove query string
    url = reQuery.sub( "", url )

    # remove port
    url = rePort.sub( "", url )

    # extract extension
    matches = reExt.search( url )
    if None != matches:
        return matches.group( 1 )
    return None

edit:从:1234

添加了对显式端口的处理

答案 7 :(得分:0)

使用urlparse,即可获得上述大部分内容:

http://docs.python.org/library/urlparse.html

然后将“路径”分开。您可以使用os.path.split拆分路径,但最后使用:8024的示例2需要手动处理。你的文件扩展名总是三个字母吗?或者总是字母和数字?使用正则表达式。

答案 8 :(得分:0)

您可以尝试rfc6266模块,如:

import requests
import rfc6266

req = requests.head(downloadLink)
headersContent = req.headers['Content-Disposition']
rfcFilename = rfc6266.parse_headers(headersContent, relaxed=True).filename_unsafe
filename = requests.utils.unquote(rfcFilename)

答案 9 :(得分:0)

这是一个相当古老的话题,但这个 oneliner 就是这样做的:

file_ext = "."+ url.split("/")[-1:][0].split(".")[-1:][0]

假设存在文件扩展名。