如何使用T-SQL从HTML内容中提取所有PDF链接
问题根因
- 原代码中
PATINDEX('%.pdf"%',@t)未指定搜索起始位置,默认从字符串开头匹配,每次都会命中整个剩余串中最后出现的.pdf",导致截取的内容包含大量无关片段,结果过长。 - 多余的
set @strtpos = PATINDEX('%href="%', @lnk)+6逻辑错误,干扰循环位置判断,导致只能返回第一个结果甚至提前终止循环。 - 剩余字符串截断的偏移计算错误,导致下次循环的匹配位置错位。
修正方案
调整逻辑:先完整提取每个href属性的内容,再判断是否为.pdf后缀,符合要求再存入结果表,修正后的函数代码如下:
ALTER function [dbo].[GetLinks] (@t nvarchar(max)) returns @Links table (link nvarchar(max)) as begin declare @strtpos int, @endpos int, @lnk nvarchar(max) -- 定位第一个href的起始位置(跳过href="共6个字符) set @strtpos = PATINDEX('%href="%', @t) + 6 while @strtpos > 6 begin -- 找到当前href对应的结束双引号位置 set @endpos = CHARINDEX('"', @t, @strtpos) -- 没有找到结束双引号直接终止循环 if @endpos = 0 break -- 截取完整的href属性值 set @lnk = SUBSTRING(@t, @strtpos, @endpos - @strtpos) -- 判断是否为pdf后缀,符合要求则插入结果 if RIGHT(@lnk, 4) = '.pdf' begin insert into @Links values(@lnk) end -- 截断剩余字符串,从当前结束双引号之后开始下一轮搜索 set @t = RIGHT(@t, LEN(@t) - @endpos) -- 定位下一个href的起始位置 set @strtpos = PATINDEX('%href="%', @t) + 6 end return end
调用测试
使用你提供的示例内容调用,去掉top 1即可返回所有符合要求的pdf链接:
select * from dbo.GetLinks(' <p>text here <a href="example.com/abc.pdf">link</a> some other text <a href="example.com">home</a> <a href="www.example.com/abc123.pdf">link 2</a></p>')
返回结果为:
| link |
|---|
| example.com/abc.pdf |
| www.example.com/abc123.pdf |
补充说明
- 如果存在
href="xxx.pdf?version=1"这类带参数的pdf链接,将RIGHT(@lnk, 4) = '.pdf'调整为PATINDEX('%.pdf%', @lnk) > 0即可匹配。 - 如果HTML中
href使用单引号包裹,只需将匹配规则中的双引号替换为单引号即可。 - 若使用SQL Server 2017及以上版本,也可以通过OPENXML解析HTML节点的方式提取,稳定性更高。
内容的提问来源于stack exchange,提问作者Faisal
相关产品推荐
相关产品推荐

