Я использую функцию автолинка большой библиотеки lxml, как описано здесь: http://lxml.de/api/lxml.html.clean-module.html
Моя проблема в том, что он обнаруживает только URL-адреса, начинающиеся с http://. Я хотел бы использовать более широкое регулярное выражение для обнаружения URL-адресов, подобное этому: http://daringfireball.net/2010/07/improved_regex_for_matching_urls
Я попытался сделать это регулярное выражение с помощью функции автоматической установки lxml без успеха. Я всегда получаю:
lxml\html\clean.py", line 571, in _link_text
host = match.group('host')
IndexError: no such group
Любые гуру python/regex, которые знают, как сделать эту работу?
Есть две вещи, которые нужно сделать, чтобы адаптировать regexp к llml autolink. Сначала завершите совпадение всего шаблона url в группе (?P<body> .. )
- это позволяет lxml знать, что входит в атрибут href=""
.
Затем завершите хост-часть в группе (?<host> .. )
и передайте параметр avoid_hosts=[]
, когда вы вызываете функцию автолинка. Причиной этого является шаблон регулярного выражения, который вы используете, не всегда находит хост (иногда часть host
будет None
), так как она соответствует частичным URL-адресам и неоднозначным url-подобным шаблонам.
Я изменил regexp, чтобы включить приведенные выше изменения, и дал тестовый пример фрагмента:
import re
import lxml.html
import lxml.html.clean
url_regexp = re.compile(r"""(?i)\b(?P<body>(?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|(?P<host>[a-z0-9.\-]+[.][a-z]{2,4}/))(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»""‘’]))""")
DOC = """<html><body>
http://foo.com/blah_blah
http://foo.com/blah_blah/.
http://www.extinguishedscholar.com/wpglob/?p=364.
http://✪df.ws/1234
rdar://1234
rdar:/1234
message://%[email protected]%3e
What about <mailto:[email protected]?subject=TEST> (including brokets).
bit.ly/foo
</body></html>"""
tree = lxml.html.fromstring(DOC)
body = tree.find('body')
lxml.html.clean.autolink(body, [url_regexp], avoid_hosts=[])
print lxml.html.tostring(tree)
Вывод:
<html><body>
<a href="http://foo.com/blah_blah">http://foo.com/blah_blah</a>
<a href="http://foo.com/blah_blah/">http://foo.com/blah_blah/</a>.
<a href="http://www.extinguishedscholar.com/wpglob/?p=364">http://www.extinguishedscholar.com/wpglob/?p=364</a>.
<a href="http://%C3%A2%C2%9C%C2%AAdf.ws/1234">http://✪df.ws/1234</a>
<a href="rdar://1234">rdar://1234</a>
<a href="rdar:/1234">rdar:/1234</a>
<a href="message://%[email protected]%3e">message://%[email protected]%3e</a>
What about <<a href="mailto:[email protected]?subject=TEST">mailto:[email protected]?subject=TEST</a>>
(including brackets).
<a href="bit.ly/foo">bit.ly/foo</a>
</body></html>
Вы действительно не даете достаточно информации, чтобы быть уверенным, но я уверен, что у вас возникают проблемы с обратными косыми чертами в регулярном выражении Gruber. Попробуйте использовать необработанную строку, которая позволяет обратную косую черту без экранирования и тройные кавычки, которые позволяют вам использовать кавычки в строке, не избегая их. Например.
re.compile(r"""(?i)\b((?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»""‘’]))""")
Host
и добавляетеhttp://
схема URL (и любые другие правила, которые вы хотите применить).