F#计算导入的URL字符串中的字符和超链接

时间:2018-12-01 15:45:04

标签: url recursion hyperlink f#

我在尝试计算从任何给定网站导入的URL字符串中的<a ... </a>超链接/标签的数量时遇到问题。以及计算同一字符串上出现的char数。后者似乎有效,到目前为止我的代码是:

let countChars (url:string) (tag: 'a) =
    let link = fetchUrl (url)
    let rec loop i count =
        if i < link.Length then
            if (link.[i] = tag) then loop (i+1) (count+1)
            else loop (i+1) count
        else count
    loop 0 0

我正在使用以下内容定义我的fetchUrl函数:

let fetchUrl (url:string) : string =
    let req = WebRequest.Create(Uri(url))
    use resp = req.GetResponse()
    use stream = resp.GetResponseStream()
    use reader = new IO.StreamReader(stream)
    in reader.ReadToEnd()

但是我目前仍然很困惑,因为我在弄清楚如何正确计算导入的url字符串上的标签时遇到了问题。在这里的示例中,我循环遍历url字符串,仅计算字符的出现(例如“ a”),但是我似乎找不到找到将其应用于解决方案的方法,在该解决方案中,我实际上是在搜索子字符串是包含<a ... </a>表达式的几个字符的表达式。

我有另一个解决方案,该解决方案实现正则表达式以尝试处理要查找的标记的实际表达式。这段代码可以运行,但是返回值却很疯狂:

let countTags (url:string) (tag:string) =
    let link = fetchUrl (url)
    let m = Regex.Match(link,tag)
    let rec loop i count =
        if i < link.Length then
            if m.Success then loop (i+1) (count+1)
            else loop (i+1) count
        else count
    loop 0 0

我通过调用以下函数获得的结果显示在右侧。

printfn "%A" (countTags "https://forum.astronomisk.dk/" "(?s)<a [^>]*?>(?<text>.*?)</a>") --> result: 75640

printfn "%A" (countTags "https://www.ku.dk/" "(?s)<a [^>]*?>(?<text>.*?)</a>") --> result: 57459

printfn "%A" (countTags "https://www.google.com/" "(?s)<a [^>]*?>(?<text>.*?)</a>") --> result: 47120

结果与我对“ crazy”的定义相对应(给出的链接在此情况下为3个简单的导入url字符串返回了大约47-75k <a href=....</a>个标记)。用相同的测试在导入的url字符串上调用第一个函数,只是查找char'a'会产生大约2500-3000的结果,根据我的说法,这是很合理的,并且似乎工作得很好。

有人可以看到我在这里想念的东西吗?我对正则表达式的实现不正确,因为它返回的结果很高吗?还是有其他方法可以计算任何给定导入的URL字符串中<a ... </a>标签的数量。我试图整天都在寻找解决方案,而无法用成功的代码最终关闭该项目。

任何帮助我修复剩下的东西的人,将不胜感激!

1 个答案:

答案 0 :(得分:1)

您的第一个问题是countTags似乎在计算您正在查看的文档的长度(如果文档包含锚标记)。

这样做的原因是Regex.Match搜索第一个匹配项,因此'm.Success'始终为真。

您想要的是Regex.Matches。这会给您一个MatchCollection,您可以接受其中的“ .Count”。

还要查看this中与锚标记匹配的正则表达式。

为了澄清,您可以

let countTags (url:string) (tag:string) =
    let link = fetchUrl url
    let regex = Regex tag
    regex.Matches(link).Count