假设我有以下字典映射域名到它的人类可读描述
domain_info = {"google.com" : "A Search Engine",
"facebook.com" : "A Social Networking Site",
"stackoverflow.com" : "Q&A Site for Programmers"}
我想从response.url获取描述,该描述返回绝对路径http://www.google.com/reader/view/
我目前的做法
url = urlparse.urlparse(response.url)
domain = url.netloc # 'www.google.com'
domain = domain.split(".") # ['www', 'google', 'com']
domain = domain[-2:] # ['google', 'com']
domain = ".".join(domain) # 'google.com'
info = domain_info[domain]
对于大量的调用来说似乎太慢了,有人可以提出另一种方法来加快速度吗?
理想的解决方案是处理任何子域并且不区分大小写
答案 0 :(得分:2)
“大量操作太慢”是什么意思?它仍然会在恒定的时间内工作(对于每个URL)并且你不能比这更好。以上似乎是一个非常好的方法。
如果你需要它更快一点(但它不会非常快),你可以编写自己的正则表达式。像"[a-zA-Z]+://([a-zA-Z0-9.]+)"
这样的东西。这将获得完整的域,而不是子域。您仍然需要进行域拆分,除非您可以在正则表达式中使用前瞻来获取最后两个段。请务必使用re.compile
快速制作正则表达式。
请注意,转移domain[-2]
可能不是您想要的。找到合适的“公司级域名”的逻辑非常复杂。例如,如果域名是google.com.au,这将为您提供“com.au”,这不太可能是您想要的 - 您可能需要“google.com.au”。
正如您所说,理想的解决方案可以处理任何子域,您可能希望迭代所有拆分。
url = urlparse.urlparse(response.url)
domain = url.netloc # 'www.google.com'
domain = domain.split(".") # ['www', 'google', 'com']
info = None
for i in range(len(domain)):
subdomain = ".".join(domain[i:]) # 'www.google.com', 'google.com', 'com'
try:
info = domain_info[subdomain]
break
except KeyError:
pass
使用上面的代码,如果匹配任何子域,您将找到它。区分大小写,这很容易。确保字典中的所有键都是小写的,并在所有其他处理之前将.lower()
应用于域。
答案 1 :(得分:1)
似乎Python 2.6标准库中的urlparse.py在调用urlparse()函数时会做很多事情。有可能通过编写一个小的URL解析器来加快速度,这个解析器只执行绝对必要的操作,而不是更多。
更新:有关域名语法的信息,请参阅this part of Wikipedia's page about DNS,它可能会为解析器提供一些想法。
答案 2 :(得分:1)
您可以考虑使用正则表达式提取没有子域的域:
'http:\/\/([^\.]+\.)*([^\.][a-zA-Z0-9\-]+\.[a-zA-Z]{2,6})(\/?|\/.*)'
import re
m = re.search('http:\/\/([^\.]+\.)*([^\.][a-zA-Z0-9\-]+\.[a-zA-Z]{2,6})(\/?|\/.*)', 'http://www.google.com/asd?#a')
print m.group(2)
答案 3 :(得分:1)
您可以使用urlparse所做的一些工作。尝试通过它返回的netloc
直接查找内容,如果必须,只返回拆分/加入:
def normalize( domain ):
domain = domain.split(".") # ['www', 'google', 'com']
domain = domain[-2:] # ['google', 'com']
return ".".join(domain) # 'google.com'
# caches the netlocs that are not "normal"
aliases = {}
def getinfo( url ):
netloc = urlparse.urlparse(response.url).netloc
if netloc in aliases:
return domain_info[aliases[netloc]]
if netloc in domain_info:
return domain_info[netloc]
main = normalize(netloc)
if main in domain_info:
aliases[netloc] = main
return domain_info[netloc]
缓存lib的相同之处:
from beaker.cache import CacheManager
netlocs = CacheManager(namespace='netloc')
@netlocs.cache()
def getloc( domain ):
try:
return domain_info[domain]
except KeyError:
domain = domain.split(".")
domain = domain[-2:]
domain = ".".join(domain)
return domain_info[domain]
def getinfo( url ):
netloc = urlparse.urlparse(response.url).netloc
return getloc( netloc )
也许它有点帮助,但它实际上取决于你拥有的各种网址。