You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

网页PDF链接爬取失败求助(F#实现)

问题分析

你当前的代码无法获取PDF链接,核心原因是这些链接并非服务器直接返回的静态HTML内容,而是页面加载后通过JavaScript动态生成的。FSharp.Data、HtmlAgilityPack这类工具只能抓取服务器返回的原始HTML源码,无法执行页面中的JavaScript,自然看不到动态渲染出来的PDF链接,和反爬机制无关。

解决方案

针对动态渲染的页面,有两种常见的解决思路:

1. 使用浏览器自动化工具(模拟真实浏览器渲染)

这类工具可以模拟真实浏览器的行为,加载页面并执行所有JavaScript,然后获取渲染完成后的完整HTML。推荐使用Playwright for .NET,它支持F#,且操作简单。

实现步骤:

  • 先安装Playwright的NuGet包:Microsoft.Playwright
  • 编写F#代码:
open Microsoft.Playwright
open System

[<EntryPoint>]
let main argv =
    async {
        use! playwright = Playwright.CreateAsync()
        use! browser = playwright.Chromium.LaunchAsync(LaunchOptions(Headless = true))
        use! page = browser.NewPageAsync()
        do! page.GotoAsync("https://www.kodis.cz/lines/region?tab=232-293")
        // 等待PDF链接所在元素加载完成
        do! page.WaitForSelectorAsync("a[href*='kodis-files.s3']") |> Async.AwaitTask
        
        // 提取所有PDF链接
        let! pdfLinks = page.QuerySelectorAllAsync("a[href*='kodis-files.s3']") |> Async.AwaitTask
        for link in pdfLinks do
            let! href = link.GetAttributeAsync("href") |> Async.AwaitTask
            printfn "%s" href
    } |> Async.RunSynchronously
    0

2. 直接调用后端API获取数据

大部分动态渲染的页面,数据都是通过AJAX请求从后端API获取的。你可以通过浏览器开发者工具找到对应的API接口,直接请求接口获取包含PDF链接的JSON数据,这种方式效率比浏览器自动化更高。

操作步骤:

  1. 打开目标页面,按下F12打开开发者工具,切换到「Network」标签
  2. 刷新页面,筛选「XHR/Fetch」类型的请求,找到返回PDF相关数据的API(通常返回JSON格式)
  3. 复制该API的请求URL、必要的请求头,然后用F#的HTTP工具(比如FSharp.Data.Http)直接请求并解析JSON

示例代码(假设找到的API为https://www.kodis.cz/api/lines/232-293):

open FSharp.Data

type LineData = JsonProvider<"""{ "pdfLinks": ["https://kodis-files.s3...pdf"] }""">

let apiUrl = "https://www.kodis.cz/api/lines/232-293"
let response = Http.RequestString(apiUrl)
let data = LineData.Parse(response)

data.PdfLinks |> List.iter (printfn "%s")
附:你提供的代码与页面结构

你的F#代码

//*******************************************
let url0 = "https://www.kodis.cz/lines/region?tab=232-293"
let document0 = HtmlDocument.Load(url0)

document0.CssSelect("div#__next") 
|> List.iter (fun item ->
                        let querySelector (tag: string) = (item.Descendants tag)                           
                        (querySelector "a")
                        |> Seq.iter (fun item ->      
                                               let url = item.AttributeValue "href"
                                               printfn "%s" url
                                    )           
             ) 

//*******************************************
let url = "https://www.kodis.cz/lines/region?tab=232-293" 
let document = HtmlDocument.Load(url)

let links =
   document.Descendants "a"
   |> Seq.choose (fun x ->
                         x.TryGetAttribute("href")
                         |> Option.map (fun a -> x.InnerText(), a.Value())
                 ) |> Seq.toList   

printfn "%A" links 

页面相关HTML结构

<div id="__next" data-reactroot="">
    <!-- many "a hrefs" with links to various stuff -->
    <main class="mt-16">
        <div class="container">         
            <div class="mb-12">
                <ul class="mb-8 grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-2">
                    <li class="Card_wrapper__ZQ5Fp">                        
                        <div class="Card_actions__HhB_f">
                            <a href="https://kodis-files.s3.eu-central-1.amazonaws.com/232_2022_12_11_2023_12_09_d02eef94bc.pdf" target="_blank" class="Button_main__pEB6O Button_secondary__R6QEg Button_md__1RLR1" data-testid="button-elementAnchor" title="Pravidelný jízdní řád">                              
                            </a>
                        </div>
                    </li>
                    <li class="Card_wrapper__ZQ5Fp">                        
                        <!-- another "a href" with a link to a pdf file -->                         
                    </li>
                    <li class="Card_wrapper__ZQ5Fp">
                        <!-- another "a href" with a link to a pdf file -->
                    </li>                   
                </ul>               
            </div>
        </div>
    </main>
</div>

内容的提问来源于stack exchange,提问作者Miroslav Husťák

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 23:35:21