【问题标题】:What is a more efficient way of extracting a value from a webpage从网页中提取价值的更有效方法是什么
【发布时间】:2012-06-28 04:35:22
【问题描述】:

我需要从网站检索一个值(可能会有所不同,我无法控制该网站)。我目前有一些有效的代码......但需要很长时间才能运行。我知道有一种大大改进的方法可以做到这一点,我只是不知道那是什么。

我已经考虑过几种替代方法,例如 Regex 和 HTMLAgilityPack(看起来很复杂,而且可能有点矫枉过正?),但如果没有尝试每种方法,我不确定哪种方法最有效。我相信还有更多的可能性。

问题甚至可能与我如何检索页面而不是我如何处理它有关。

    Dim GETURL As WebRequest
    GETURL = WebRequest.Create("http://www.example.com")
    Dim objStream As Stream = GETURL.GetResponse.GetResponseStream()

    Dim objReader As New StreamReader(objStream)
    Dim sLine As String = ""
    Dim a As Integer = 0
    Dim result As String = ""
    Do While Not sLine Is Nothing
        a += 1
        sLine = objReader.ReadLine
        If Not sLine Is Nothing Then
            result += sLine
        End If
    Loop

    Dim startTag as string ="<some html tag>"
    Dim endTag as string ="<closing tag>"
    Dim firstIndex As Integer = result.IndexOf(startTag) + startTag.Length
    result = result.Substring(firstIndex, result.Length - firstIndex)
    Dim RequiredVal As String = result.Substring(0, result.IndexOf(endTag))

请注意,我确实意识到这段代码的效率非常低,但与其尝试加载不同的排列(并且可能仍然有相当低效的代码),我想我会先征求一些专家的建议 :-)

更新:

由于我没有得到任何回应(也许我的问题有点太模糊了?)我一直在努力提高自己的效率。通过使用 WebCient.DownloadString(),我设法将运行时间减少了约 50%。这很好,但我怀疑我可以改进从页面中提取数据。请参阅下面的更新代码:

    Dim client As New WebClient()
    Dim result As String = client.DownloadString("http://www.example.com")

    Dim startTag as string ="<some html tag>"
    Dim endTag as string ="<closing tag>"
    Dim firstIndex As Integer = result.IndexOf(startTag) + startTag.Length
    result = result.Substring(firstIndex, result.Length - firstIndex)
    Dim RequiredVal As String = result.Substring(0, result.IndexOf(endTag))

任何建议都将不胜感激。

【问题讨论】:

    标签: .net performance web-scraping


    【解决方案1】:

    如果您的问题在于等待来自网络请求的响应,那么您用来解析它的实际引擎或技术可能与性能的关系要小得多,而不仅仅是同步地等待来自网络的每个响应。如果您要抓取的页面列表很长,那么您可以通过异步运行同时请求来做得更好。目前尚不清楚这是怎么回事。

    尝试CsQuery - 也在NuGet - jQuery 的新 C# 端口,它应该可以满足您的需求。它具有同步和异步抓取数据的方法,因此如果您确实想启动并行 Web 请求,它可以开箱即用。不过,在最基本的层面上,代码是这样同步执行的:

    CQ doc = CQ.CreateFromUrl("http://www.jquery.com");
    
    string allStuffInsideTag = doc["sometag"].Contents().RenderSelection();
    

    它像 jquery 一样工作。 “CQ”对象与 jQuery 对象相同。 Contents 是返回元素所有子元素的 jQuery 方法; RenderSelection 是一个 CsQuery 方法,它呈现选择集中每个元素的完整 HTML。因此,这将返回每个 sometag 块内所有内容的全文和 html。

    它还为所有常见选择器类型索引每个文档,并且比 HTML Agility Pack 快得多。

    【讨论】:

    • 谢谢。 TBH 我不确定问题是等待响应还是处理。现在,你提到它,更有可能是那些需要时间的请求。我没有长长的清单(至少在时间紧迫的情况下)。最多有 10 个请求。执行请求异步可能是一种选择,尽管它可能会有点混乱,因为我需要它们都返回一个值,然后再继续。 CsQuery 看起来确实是一个优雅的解决方案,如果它比您所说的 Agility 更快,那么令人印象深刻。
    • 等待所有异步回调应该不会太难管理。在 C#5 中,您可以使用 Tasks.WaitAll: msdn.microsoft.com/en-us/library/dd270695.aspx .. 我个人仍在使用 VS2010,所以我确实在 CsQuery 中实现了类似的东西,请参阅When.All under: github.com/jamietre/csquery#promises CsQuery 对于选择器来说比 HAP 快得多,实际上我只是运行了一些数字:blog.outsharked.com/2012/06/csquery-performance-vs-fizzler.html 但同样 - 取决于您提取的内容和页面的大小 - 您可能只是在等待服务器。
    • 您好,抱歉,有一段时间没来,因为想解决一些汽车故障。我想我可能会请求并处理一次关键页面,然后在向用户发送响应后处理其余页面。然后我会看看响应时间是什么样的,如果我需要进一步优化(我会在某个时候做),我会记住你的建议。您的许多建议对其他项目也很有帮助,非常感谢您的意见。
    【解决方案2】:

    使用WatiN 或更好的HTML Agility Pack

    【讨论】:

    • 嗨,谢谢。我以前没有见过 WatiN,我认为它不太适合特定问题,但对于另一个项目来说确实很有趣。我同意 HTML 敏捷包是一种可能性。我只是担心添加一个像这样的整个库对于这个小功能来说太过分了。在我学习如何使用它之前,它可能是一个很大的改进吗?
    猜你喜欢
    • 2022-11-23
    • 2016-11-30
    • 1970-01-01
    • 2020-02-13
    • 2019-09-24
    • 2019-10-20
    • 2014-12-22
    • 2021-04-08
    • 1970-01-01
    相关资源
    最近更新 更多