在 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)://' 部分。如果是,则将它们添加到结果中。
我想在我的列表中提取整个独特的 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)://' 部分。如果是,则将它们添加到结果中。