在 Python 中提取唯一网址

Extracting unique URLs in Python

我想在我的列表中提取整个独特的 url 项目,以便继续进行网络抓取项目。尽管我这边有大量 URL 列表,但我想在这里生成极简场景来解释我这边的主要问题。假设我的列表是这样的:

url_list = ["https://www.ox.ac.uk/",
            "http://www.ox.ac.uk/",
            "https://www.ox.ac.uk",
            "http://www.ox.ac.uk",
            "https://www.ox.ac.uk/index.php",
            "https://www.ox.ac.uk/index.html",
            "http://www.ox.ac.uk/index.php",
            "http://www.ox.ac.uk/index.html",
            "www.ox.ac.uk/",
            "ox.ac.uk",
            "https://www.ox.ac.uk/research"        
            ]
def ExtractUniqueUrls(urls):
    pass

ExtractUniqueUrls(url_list)

对于极简方案,我希望只有两个唯一的 url,即“https://www.ox.ac.uk”和“https://www.ox.ac”。uk/research”。尽管每个 url 元素都有一些差异,例如“http”、“https”,结尾为“/” ", 没有结尾 "/", index.php, index.html;他们都指向完全相同的网页。可能还有其他一些我已经错过的可能性(如果你发现了,请记住它们)。无论如何,使用 Python 3 处理此问题的正确有效方法是什么?

我不是在寻找一种硬编码的解决方案,比如单独关注每个案例。例如,我不想手动检查 url 末尾是否有“/”。可能有其他软件包(例如 urllib 有更好的解决方案?为此,我查看了urllib.parse的方法,但至今没有找到合适的解决方案。 谢谢

编辑:为了更好地解释,我在最后的列表中添加了一个示例。否则,您可能会认为我正在寻找根 url,但事实并非如此。

仅关注您揭露的所有案例:

url_list = ["https://www.ox.ac.uk/",
            "http://www.ox.ac.uk/",
            "https://www.ox.ac.uk",
            "http://www.ox.ac.uk",
            "https://www.ox.ac.uk/index.php",
            "https://www.ox.ac.uk/index.html",
            "http://www.ox.ac.uk/index.php",
            "http://www.ox.ac.uk/index.html",
            "www.ox.ac.uk/",
            "ox.ac.uk",
            "ox.ac.uk/research",
            "ox.ac.uk/index.php?12"]

def url_strip_gen(source: list):
    replace_dict = {".php": "", ".html": "", "http://": "", "https://": ""}

    for url in source:
        for key, val in replace_dict.items():
            url = url.replace(key, val, 1)
        url = url.rstrip('/')

        yield url[4:] if url.startswith("www.") else url


print(set(url_strip_gen(url_list)))
{'ox.ac.uk/index?12', 'ox.ac.uk/index', 'ox.ac.uk/research', 'ox.ac.uk'}

如果 url 包含像 www.htmlsomething 这样的 .html,则不包括这种情况,在这种情况下,它可以用 urlparse 进行补偿,因为它存储路径和 url分别如下:

>>> import pprint
>>> from urllib.parse import urlparse
>>> a = urlparse("http://ox.ac.uk/index.php?12")
>>> pprint.pprint(a)
ParseResult(scheme='http', netloc='ox.ac.uk', path='/index.php', params='', query='12', fragment='')

但是,如果没有方案:

>>> a = urlparse("ox.ac.uk/index.php?12")
>>> pprint.pprint(a)
ParseResult(scheme='', netloc='', path='ox.ac.uk/index.php', params='', query='12', fragment='')

所有主机转到 path 属性。

为了弥补这一点,我们要么需要删除 scheme 并为所有添加一个,要么检查 url 是否以 scheme 开头,否则添加一个。 Prior更容易实现。

replace_dict = {"http://": "", "https://": ""}

    for url in source:
        # Unify scheme to HTTP
        for key, val in replace_dict.items():
            url = url.replace(key, val, 1)

        url = "http://" + (url[4:] if url.startswith("www.") else url)
        parsed = urlparse(url)

有了这个,您可以保证通过 urlparse 单独控制 url 的每个部分。但是,由于您没有指定 url 应该考虑哪个参数才足够 唯一 ,我将把这个任务留给您。

这是一个快速而肮脏的尝试:

def extract_unique_urls(url_list):

    unique_urls = []
    for url in url_list:
        # Removing the 'https://' etc. part
        if url.find('//') > -1:
            url = url.split('//')[1]
        # Removing the 'www.' part
        url = url.replace('www.', '')
        # Removing trailing '/'
        url = url.rstrip('/')
        # If not root url then inspect the last part of the url
        if url.find('/') > -1:
            # Extracting the last part
            last_part = url.split('/')[-1]
            # Deciding if to keep the last part (no if '.' in it)
            if last_part.find('.') > -1:
                # If no to keep: Removing last part and getting rid of
                # trailing '/'
                url = '/'.join(url.split('/')[:-1]).rstrip('/')
        # Append if not already in list
        if url not in unique_urls:
            unique_urls.append(url)

    # Sorting for the fun of it
    return sorted(unique_urls)

我敢肯定它没有涵盖所有可能的情况。但如果情况并非如此,也许您可​​以扩展它。我也不确定您是否想保留 'http(s)://' 部分。如果是,则将它们添加到结果中。