【问题标题】:Regex check if link is to a file正则表达式检查链接是否指向文件
【发布时间】:2019-07-29 09:39:13
【问题描述】:

如何检查给定的链接(url)是指向文件还是另一个网页?

我的意思是:

目前我正在做一个非常hacky的多步骤检查,它还需要相对于绝对链接进行转换,如果丢失则添加http前缀并删除'#'锚链接/参数才能工作。我也不确定我是否将所有可能存在的页面扩展列入白名单

import re
def check_file(url):
    try:
        sub_domain = re.split('\/+', url)[2] # part after '2nd slash(es)''
    except:
        return False # nothing = main page, no file
    if not re.search('\.', sub_domain):
        return False # no dot, no file
    if re.search('\.htm[l]{0,1}$|\.php$|\.asp$', sub_domain):
        return False # whitelist some page extensions
    return True

tests = [
    'https://www.stackoverflow.com',
    'https://www.stackoverflow.com/randomlink',
    'https:////www.stackoverflow.com//page.php',
    'https://www.stackoverflow.com/page.html',
    'https://www.stackoverflow.com/page.htm',
    'https://www.stackoverflow.com/file.exe',
    'https://www.stackoverflow.com/image.png'
]

for test in tests:
    print(test + '\n' + str(check_file(test)))
# False: https://www.stackoverflow.com
# False: https://www.stackoverflow.com/randomlink
# False: https:////www.stackoverflow.com//page.php
# False: https://www.stackoverflow.com/page.html
# False: https://www.stackoverflow.com/page.htm
# True: https://www.stackoverflow.com/file.exe
# True: https://www.stackoverflow.com/image.png

是否有针对此问题的干净、单一的正则表达式匹配解决方案或具有已建立功能的库来解决此问题?我想一定有人在我之前遇到过这个问题,但不幸的是我在 SO 上找不到解决方案。

【问题讨论】:

  • 我认为你不能仅仅通过查看 url 就可以明确地确定 url 将为你提供的数据类型。如果 Web 服务器真的想要,它可以决定在您访问“image.png”时提供一个 html 文件。或者,当您转到“page.htm”时,它可以提供 mp3。或文件类型和扩展名的任何其他组合。要获得准确的类型数据,您需要检查 http 标头的 MIME 类型。
  • 谢谢@Kevin,显然我一直在尝试解决错误的问题。我想我会按照你的建议去做

标签: python html regex hyperlink


【解决方案1】:

urlparse 是你的朋友。

from urllib.parse import urlparse

def check_file(url):
    path = urlparse(url).path  # extract the path component of the URL
    name = path.rsplit('/', 1)[-1]  # discard everything before the last slash

    if '.' not in name:  # if there's no . it's definitely not a file
        return False

    ext = path.rsplit('.', 1)[-1]  # extract the file extension
    return ext not in {'htm', 'html', 'php', 'asp'}

这可以通过使用pathlib 模块进一步简化:

from urllib.parse import urlparse
from pathlib import PurePath

def check_file(url):
    path = PurePath(urlparse(url).path)
    ext = path.suffix[1:]

    if not ext:
        return False

    return ext not in {'htm', 'html', 'php', 'asp'}

【讨论】:

    【解决方案2】:

    Aran-Fey 的答案适用于行为良好的网页,这些网页占网络的 99.99%。但是没有规则说以特定扩展名结尾的 url 必须解析为特定类型的内容。配置不佳的服务器可能会为对名为“example.png”的页面的请求返回 html,或者它可能会为名为“example.php”的页面或任何其他内容类型和文件扩展名的组合返回 mpeg。

    获取 url 内容类型信息的最准确方法是实际访问该 url 并检查其标题中的内容类型。大多数 http 接口库都有一种只从站点检索标题信息的方法,因此即使对于非常大的页面,此操作也应该相对快速。例如,如果您使用requests,您可能会这样做:

    import requests
    def get_content_type(url):
        response = requests.head(url)
        return response.headers['Content-Type']
    
    test_cases = [
        "http://www.example.com",
        "https://i.stack.imgur.com/T3HH6.png?s=328&g=1",
        "http://php.net/manual/en/security.hiding.php",
    ]    
    
    for url in test_cases:
        print("Url:", url)
        print("Content type:", get_content_type(url))
    

    结果:

    Url: http://www.example.com
    Content type: text/html; charset=UTF-8
    Url: https://i.stack.imgur.com/T3HH6.png?s=328&g=1
    Content type: image/png
    Url: http://php.net/manual/en/security.hiding.php
    Content type: text/html; charset=utf-8
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-06
      相关资源
      最近更新 更多