匹配HTML标签中 href 属性的正则表达式
正则表达式代码
import re
PREFIXES_TO_IGNORE = ("javascript:", "mailto:", "#")
SUFFIXES_TO_IGNORE = (
".css",
".js",
".ico",
".png",
".jpg",
".jpeg",
".gif",
".svg",
".csv",
".bz2",
".zip",
".epub",
)
SUFFIXES_TO_IGNORE_REGEX = (
"(?!" + "|".join([re.escape(s) + r"[\#'\"]" for s in SUFFIXES_TO_IGNORE]) + ")"
)
PREFIXES_TO_IGNORE_REGEX = (
"(?!" + "|".join([re.escape(s) for s in PREFIXES_TO_IGNORE]) + ")"
)
import re
pattern = re.compile(
rf'href=["\']{PREFIXES_TO_IGNORE_REGEX}((?:{SUFFIXES_TO_IGNORE_REGEX}.)*?)(?:[\#\'"]|\/[\#\'"])'
)
matches = pattern.findall(html)
表达式解析
PREFIXES_TO_IGNORE
和 SUFFIXES_TO_IGNORE
变量用于 过滤不需要的链接,并且两个正则表达式变量 PREFIXES_TO_IGNORE_REGEX
和 SUFFIXES_TO_IGNORE_REGEX
来用于正则匹配。让我们解析它们的作用:
解析 PREFIXES_TO_IGNORE_REGEX
PREFIXES_TO_IGNORE = ("javascript:", "mailto:", "#")
PREFIXES_TO_IGNORE_REGEX = (
"(?!" + "|".join([re.escape(s) for s in PREFIXES_TO_IGNORE]) + ")"
)
解析
re.escape(s)
确保javascript:
,mailto:
,#
这些特殊字符不会影响正则语法。"|".join([...])
组合成javascript:|mailto:|#
,作为|
分隔的选项。"(?!...)"
是 负向先行断言,表示 “不以这些前缀开头”。
示例
PREFIXES_TO_IGNORE_REGEX = "(?!javascript:|mailto:|#)"
作用
确保匹配的 href
不能以 javascript:
, mailto:
, #
开头。
例如:
href="javascript:void(0)"
❌ 不匹配href="mailto:someone@example.com"
❌ 不匹配href="#section1"
❌ 不匹配href="https://example.com"
✅ 匹配
解析 SUFFIXES_TO_IGNORE_REGEX
SUFFIXES_TO_IGNORE = (
".css", ".js", ".ico", ".png", ".jpg", ".jpeg", ".gif", ".svg",
".csv", ".bz2", ".zip", ".epub",
)
SUFFIXES_TO_IGNORE_REGEX = (
"(?!" + "|".join([re.escape(s) + r"[\#'\"]" for s in SUFFIXES_TO_IGNORE]) + ")"
)
解析
-
re.escape(s) + r"[\#'\"]"
re.escape(s)
确保后缀被正确处理(避免.
被误解释为正则中的通配符)。r"[\#'\"]"
表示文件名 后面必须是#
、'
或"
之一,确保.css
,.js
这些后缀确实是文件扩展名,而不是 URL 中间部分。
-
"(?!...)"
是负向先行断言,表示 “不以这些后缀结尾”。
示例
SUFFIXES_TO_IGNORE_REGEX = "(?!\.css[\#'\"]|\.js[\#'\"]|\.png[\#'\"]|\.jpg[\#'\"]|\.zip[\#'\"])"
作用
确保 href
不指向这些后缀的文件,例如:
href="styles.css"
❌ 不匹配href="script.js"
❌ 不匹配href="image.png"
❌ 不匹配href="https://example.com/page.html"
✅ 匹配href="https://example.com/download.zip"
❌ 不匹配
如何用于 href
解析
最终的正则:
href=["']{PREFIXES_TO_IGNORE_REGEX}((?:{SUFFIXES_TO_IGNORE_REGEX}.)*?)
(?:[\#'"]|\/[\#'"])
综合作用:
- 过滤掉
javascript:
、mailto:
、#
开头的href
- 过滤掉
.css
,.js
,.png
,.jpg
这些后缀的href
- 匹配
href
属性中的有效URL
应用示例
import re
html = '''
<a href="https://example.com">Valid Link</a>
<a href="mailto:user@example.com">Mail Link</a>
<a href="javascript:void(0)">JS Link</a>
<a href="style.css">CSS File</a>
<a href="image.png">Image File</a>
'''
pattern = re.compile(
rf'href=["\']{PREFIXES_TO_IGNORE_REGEX}((?:{SUFFIXES_TO_IGNORE_REGEX}.)*?)(?:[\#\'"]|\/[\#\'"])'
)
matches = pattern.findall(html)
print(matches)
输出
['https://example.com']
这说明:
✅ 成功匹配 https://example.com
❌ 忽略了 mailto:
、javascript:
、.css
、.png
等链接
总结
正则表达式:
- 忽略无效前缀(
javascript:
,mailto:
,#
) - 忽略无效后缀(
.css
,.js
,.png
等) - 适用于网页解析/爬虫的
href
过滤
如果你正在写一个网页爬虫或URL提取器,这个正则可以有效剔除不需要的链接,让你的数据更干净!
代码链接:https://github.com/langchain-ai/langchain/blob/master/libs/core/langchain_core/utils/html.py