这是我在某个字符串中查找 URL 的正则表达式(我需要域的组,因为进一步的操作是基于域的),我注意到在这个示例中的某些字符串“fffffffff”非常慢,有什么明显的我遗漏了吗?
>>> URL_ALLOWED = r"[a-z0-9$-_.+!*'(),%]"
>>> URL_RE = re.compile(
... r'(?:(?:https?|ftp):\/\/)?' # protocol
... r'(?:www.)?' # www
... r'(' # host - start
... r'(?:'
... r'[a-z0-9]' # first character of domain('-' not allowed)
... r'(?:'
... r'[a-z0-0-]*' # characters in the middle of domain
... r'[a-z0-9]' # last character of domain('-' not allowed)
... r')*'
... r'\.' # dot before next part of domain name
... r')+'
... r'[a-z]{2,10}' # TLD
... r'|' # OR
... r'(?:[0-9]{1,3}\.){3}[0-9]{1,3}' # IP address
... r')' # host - end
... r'(?::[0-9]+)?' # port
... r'(?:\/%(allowed_chars)s+/?)*' # path
... r'(?:\?(?:%(allowed_chars)s+=%(allowed_chars)s+&)*' # GET params
... r'%(allowed_chars)s+=%(allowed_chars)s+)?' # last GET param
... r'(?:#[^\s]*)?' % { # anchor
... 'allowed_chars': URL_ALLOWED
... },
... re.IGNORECASE
... )
>>> from time import time
>>> strings = [
... 'foo bar baz',
... 'blah blah blah blah blah blah',
... 'f' * 10,
... 'f' * 20,
... 'f' * 30,
... 'f' * 40,
... ]
>>> def t():
... for string in strings:
... t1 = time()
... URL_RE.findall(string)
... print string, time() - t1
...
>>> t()
foo bar baz 3.91006469727e-05
blah blah blah blah blah blah 6.98566436768e-05
ffffffffff 0.000313997268677
ffffffffffffffffffff 0.183916091919
ffffffffffffffffffffffffffffff 178.445468903
是的,我知道还有另一种解决方案可以使用非常简单的正则表达式(例如包含点的单词)并稍后使用 urlparse 来获取域,但是当我们在 URL 中没有协议时,urlparse 无法按预期工作:
>>> urlparse('example.com')
ParseResult(scheme='', netloc='', path='example.com', params='', query='', fragment='')
>>> urlparse('http://example.com')
ParseResult(scheme='http', netloc='example.com', path='', params='', query='', fragment='')
>>> urlparse('example.com/test/test')
ParseResult(scheme='', netloc='', path='example.com/test/test', params='', query='', fragment='')
>>> urlparse('http://example.com/test/test')
ParseResult(scheme='http', netloc='example.com', path='/test/test', params='', query='', fragment='')
>>> urlparse('example.com:1234/test/test')
ParseResult(scheme='example.com', netloc='', path='1234/test/test', params='', query='', fragment='')
>>> urlparse('http://example.com:1234/test/test')
ParseResult(scheme='http', netloc='example.com:1234', path='/test/test', params='', query='', fragment='')
是的,预先添加 http:// 也是一个解决方案(我仍然不能 100% 确定是否没有其他 urlparse 问题)但我很好奇这个正则表达式有什么问题