我已经看到了其他问题,这些问题将解析所有普通链接或字符串中的所有锚标记,但没有任何内容同时解析。
理想情况下,正则表达式将能够解析这样的字符串(我正在使用Python):
>>> import re
>>> content = '
<a href="http://www.google.com">http://www.google.com</a> Some other text.
And even more text! http://stackoverflow.com
'
>>> links = re.findall('some-regular-expression', content)
>>> print links
[u'http://www.google.com', u'http://stackoverflow.com']
是否可以生成一个不会导致返回重复链接的正则表达式?有更好的方法吗?
答案 0 :(得分:1)
通常为you should never parse HTML with regular expressions,因为HTML不是常规语言。在这里,你似乎只想获得它们在A元素或文本中的所有http链接。如何获取所有内容然后删除重复项?
尝试类似
的内容set(re.findall("(http:\/\/.*?)[\"' <]", content))
并查看它是否符合您的目的。
答案 1 :(得分:1)
无论你做什么,它都会变得凌乱。然而,90%的解决方案可能类似于:
r'<a\s[^>]*>([^<]*)</a>|\b(\w+://[^<>\'"\t\r\n\xc2\xa0]*[^<>\'"\t\r\n\xc2\xa0 .,()])'
由于该模式有两个组,它将返回一个2元组的列表;加入他们,你可以使用列表理解甚至地图:
map(''.join, re.findall(pattern, content))
如果你想要锚点的src
属性而不是链接文本,那么模式会变得更加混乱:
r'<a\s[^>]*src=[\'"]([^"\']*)[\'"][^>]*>[^<]*</a>|\b(\w+://[^<>\'"\t\r\n\xc2\xa0]*[^<>\'"\t\r\n\xc2\xa0 .,()])'
或者,你可以让模式的后半部分选择src
属性,这也减少了字符串连接的需要:
r'\b\w+://[^<>\'"\t\r\n\xc2\xa0]*[^<>\'"\t\r\n\xc2\xa0 .,()]'
一旦你有了这么多,你可以用看起来像链接的东西替换任何找到的链接,搜索'://'
,并更新模式以收集错过的内容。您可能还需要清理误报,特别是最后的垃圾。 (这种模式必须找到包含空格的链接,以纯文本形式显示,因此特别容易出现过度贪婪。)
警告:不要依赖于此以用于将来的用户输入,尤其是当安全性在线时。它最好仅用于从现有数据手动收集链接。
答案 2 :(得分:0)
编写与所有有效网址匹配的正则表达式模式为tricky business。
如果您要查找的只是在任意字符串中检测简单的http / https网址,我可以为您提供此解决方案:
>>> import re
>>> content = '<a href="http://www.google.com">http://www.google.com</a> Some other text. And even more text! http://stackoverflow.com'
>>> re.findall(r"https?://[\w\-.~/?:#\[\]@!$&'()*+,;=]+", content)
['http://www.google.com', 'http://www.google.com', 'http://stackoverflow.com']
查找以http://或https://开头的字符串,后跟一个或多个有效字符。
为避免重复输入,请使用set()
:
>>> list(set(re.findall(r"https?://[\w\-.~/?:#\[\]@!$&'()*+,;=]+", content)))
['http://www.google.com', 'http://stackoverflow.com']
答案 3 :(得分:0)
您不应该使用正则表达式从HTML中提取内容。您应该使用HTML解析器。
如果您还想从页面文本中提取内容,那么您应该单独执行此操作。
以下是使用lxml
:
# -*- coding: utf8 -*-
import lxml.html as lh
import re
html = """
is.gd/test<a href="http://www.google.com">http://www.google.com</a> Some other text.
And even more text! http://stackoverflow.com
here's a url bit.ly/test
"""
tree = lh.fromstring(html)
urls = set([])
for a in tree.xpath('//a'):
urls.add(a.text)
for text in tree.xpath('//text()'):
for url in re.findall(r'(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:\'".,<>?«»“”‘’]))', text):
urls.add(url[0])
print urls
<强>结果:强>
set(['http://www.google.com', 'bit.ly/test', 'http://stackoverflow.com', 'is.gd/test'])
此处的网址匹配正则表达式:http://daringfireball.net/2010/07/improved_regex_for_matching_urls
答案 4 :(得分:-1)
不,它无法像这样解析字符串。 Regexp能够进行简单的匹配,你只能使用一个或两个正则表达式来解析复杂的语法为html。