使用FSharp.Data解析HTML:提取带href属性的a标签PDF链接
使用FSharp.Data提取HTML中的PDF链接
问题背景
我正在用F#和FSharp.Data库解析HTML,目前能提取<head>里的meta标签数据,但换成查找带href属性的<a>标签(获取所有PDF链接,比如file1.pdf)时却得不到结果。现有代码能获取meta标签的name属性值,但把Descendants参数改成"a"就失效了。
当前代码:
#r @"C:\...\.nuget\packages\fsharp.data\5.0.2\lib\netstandard2.0\FSharp.Data.dll" open Fsharp.Data let html = HtmlDocument.Load("test.html") let d = html.Descendants [ "meta" ] |> Seq.choose (fun x -> x.TryGetAttribute("name") |> Option.map (fun a -> a.Value())) |> Seq.toList
测试HTML示例:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="pragma" content="no-cache"> ... <meta name="description" content="...."> <meta name="robots" content="all"> <meta name="keywords" content="keywords..."> <link rel='stylesheet' href='*****.css' type='text/css'/> <link rel='stylesheet' href='*****.css' type='text/css' title='***'/> <link rel='alternate stylesheet' href='../styles.css' type='text/css' title='***'/> <script src='../Menu.js' type='text/javascript'></script> <script type='text/javascript'> if (isIE() || isChrome()) { setActiveStyleSheet(SET_SS); } setRequestedStyleSheet(); </script> </head> <body onload='init()'> <div id='Menu'><input id='checkBox' type='checkbox' onclick='toggleStyleSheet()' title='Show'></div> <iframe class="A" > </iframe> <table class="CenteredTable" border="0" space="preserve"> <colgroup space="preserve" span="1"> <col class="col1" space="preserve" span="1"></col> </colgroup> <tbody space="preserve"> <tr id="1_title" space="preserve"> <td space="preserve" rowspan="1" colspan="1"> <a id="fsdf" space="preserve" shape="rect"></a> <div class="sect2" space="preserve"> <div class="titlepage" space="preserve"> <div space="preserve"> <div space="preserve"> <h3 class="title" space="preserve"> <a id="" space="preserve" shape="rect"></a> <span class="_default" space="preserve">TEXT</span> <a class="link" href="../file1.pdf" target="_blank" space="preserve" shape="rect"> <img src="../images/app_pdf.png" space="preserve"></img> </a> </h3> </div> </div> <div space="preserve"></div> </div> </div> </td> </tr> <tr id="2_title" space="preserve"> .... </tr> </tbody> </table> <iframe class="B" > </iframe> </body> </html>
解决方案
核心问题是命名空间大小写错误,以及缺少对PDF链接的筛选逻辑,修正后的代码如下:
#r @"C:\...\.nuget\packages\fsharp.data\5.0.2\lib\netstandard2.0\FSharp.Data.dll" open FSharp.Data // 修正命名空间大小写:FSharp.Data而非Fsharp.Data let html = HtmlDocument.Load("test.html") let pdfLinks = html.Descendants ["a"] |> Seq.choose (fun aTag -> // 1. 尝试获取href属性,忽略无href的a标签 aTag.TryGetAttribute("href") // 2. 筛选出链接以.pdf结尾的项(大小写不敏感) |> Option.filter (fun attr -> attr.Value().EndsWith(".pdf", System.StringComparison.OrdinalIgnoreCase)) // 3. 提取href属性的值 |> Option.map (fun attr -> attr.Value())) |> Seq.toList
代码说明
- 命名空间修正:FSharp.Data的命名空间是大写的
F和S,之前的Fsharp.Data会导致API调用异常,这是无法获取<a>标签的关键原因。 - 筛选逻辑:
TryGetAttribute安全获取属性,避免无href的<a>标签引发错误;Option.filter只保留PDF链接,用OrdinalIgnoreCase确保.PDF这类大写后缀也能被识别;- 最终提取所有符合条件的href值并转为List。
可选:转换相对路径为绝对路径
如果需要把示例中的相对路径(如../file1.pdf)转为绝对路径,可以借助System.Uri:
open System let baseUrl = Uri("https://your-website-base-url.com/") let absolutePdfLinks = pdfLinks |> List.map (fun relativePath -> Uri(baseUrl, relativePath).AbsoluteUri)
内容的提问来源于stack exchange,提问作者RAh
相关产品推荐
相关产品推荐

