我尝试从网页抓取pdf文件(https://kodis-files.s3 .....
)的链接,但没有成功。
我使用f#,但我希望那些用其他。net语言编码的人会发现代码并不难读。
我使用了这两种方法(代码被简化了,结果被打印出来,而不是用在其他地方):
//*******************************************
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
两种变体都会抓取网站上的所有链接pdf文件链接除外.
到相关网页的链接在代码中。我已经提取了部分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>
我做错了什么?有没有可能用一些"防刮"剂?SW受雇于网站的创建者?
编辑:正如Jim Foye所建议的,pdf链接似乎是由JavaScript创建的,因此不可能在FSharp.Data
或HtmlAgilityPack
或.Net.WebClient
或.Net.Http.HttpClient
或wget
的帮助下被抓取。如果这个问题的唯一解决方案是获得html代码相同的方式作为浏览器保存代码,请参阅相关问题。如果不能,请在这里提出解决方法。
我在链接的问题中看到你找到了一种方法来做到这一点。如果你能找到页面是如何由JavaScript生成的(正如你所做的),那么直接获取数据是最优的。
然而,如果这不起作用,也有一个很好的f#库顶盖,它可以让你自动运行浏览器——这样你就可以在浏览器中加载页面,然后提取链接:
#r "nuget:canopy"
open canopy
open canopy.classic
// Download chromedriver.exe from
// https://chromedriver.chromium.org/downloads
canopy.configuration.chromeDir <- "c:/temp/driver"
start chrome
url "https://www.kodis.cz/lines/region?tab=232-293"
你可以在f# Interactive中以交互方式运行上面的代码,等待页面加载&执行如下命令:
for el in elements "a" do
let href = el.GetAttribute("href")
if href.EndsWith("pdf") then
printfn "%A" href
2023年4月7日,编辑 ***********************************
如果不在FS Interactive中运行代码,则可能需要在for
循环之前添加如下代码:
let linksShown () = (elements ".Card_wrapper__ZQ5Fp").Length >= 11
//a condition for waitFor
compareTimeout <- 10.0 //probably needed for slow connections
waitFor linksShown //waiting until the needed number of elements are downloaded
还可以查看其他Canopy的内容,如waitforElement
。
编辑 **********************************************
如果页面只是渐进式加载数据,这可能也很有用。例如,你可以模拟点击"Další"按钮加载更多数据:
click (elementWithText "a" "Další")