【问题标题】:Scrape JavaScript array data with CsQuery使用 CsQuery 抓取 JavaScript 数组数据
【发布时间】:2014-12-23 09:03:43
【问题描述】:

我想抓取的一些数据包含在页面 JavaScript 中。它看起来类似于这种模式:

<script type="text/javascript">
        arrayName["field1"] = 12;
        arrayName["field2"] = 42;
        arrayName["field3"] = 1442;
</script>
<script type="text/javascript">
        arrayName["field4"] = 62;
        arrayName["field5"] = 3;
        arrayName["field6"] = 542;
</script>

它与大量其他 Javascript 混在一起。我需要获取这些值。

我是这样开始的:

var dom = CQ.CreateFromUrl("http://somesite.xxx");

CQ script = dom["script[type='text/javascript']"];

但我现在想不出如何获取这些数据。是创建正则表达式并遍历所有内容的唯一方法,还是有另一种性能更好的方法?

我看不到如何将 CSS 选择器用于实际的 JavaScript 代码。我应该尝试不同的方法吗?

【问题讨论】:

    标签: c# csquery


    【解决方案1】:

    您似乎真的在寻找服务器端 Javascript 引擎 - CsQuery 可以很容易地为您获取脚本标签的内容,但是您需要实际运行脚本,然后才能引用实体被创建。虽然理论上可以创建某种查询语言来解析脚本行,但实际情况是,这基本上只是运行它。如果您只需要提取包含简单赋值的特定行,而上下文并不重要,那么您可能正在寻找像正则表达式(甚至 grep)这样简单的东西来过滤掉您需要的内容。

    我使用了 Neosis V8 包装器 -- http://javascriptdotnet.codeplex.com/ -- 也在 nuget 上作为 Neosis.Javascript。

    它和任何东西一样快(因为它在引擎盖下使用了 Google 的 V8 引擎);唯一真正的缺点是它不是一个纯 .NET 解决方案,但一旦设置它就非常轻松。使用它的一个例子是在我的项目https://github.com/jamietre/SharpLinter 中,它使用它来运行 JsHint。

    有多种 100% .NET Javascript 引擎,例如 Jint、IronJS 和 Jurassic。我以前使用过侏罗纪,它可能是最快的,因为它编译为字节码。它出人意料地完整,但并未真正得到积极开发,因此可能很难获得太多支持。但它们都比 V8 慢得多,而且除了没有非 .NET 引用之外没有提供任何真正的优势。

    除非你真的非常需要它是 100% .net,否则只需使用 JavscriptDotNet。

    【讨论】:

    • 感谢 Jamie,我正在走这条路。执行与页面分开的脚本有点棘手,但我正在使用正则表达式来整理东西,它似乎正在工作。还只是想我会非常感谢 CsQuery。我之前使用过 HAP,而 CsQuery 好得多,它为我节省了很多时间!
    【解决方案2】:

    它可能不会很快,但您可以尝试为此使用 WebBrowser 控件。让它浏览到页面,然后执行您自己的 Javascript 来检索数据。示例:

    var url = "http://example.com";
    object arrayName;
    var thread = new Thread(() =>
    {
        var browser = new WebBrowser { ScriptErrorsSuppressed = true };
    
        // prevent popups
        browser.NewWindow += (sender, e) =>
        {
            e.Cancel = true;
        };
    
        browser.DocumentCompleted += (sender, eventArgs) =>
        {
            // call the Javascript eval() function, and pass it a string of what we want to evaluate. By passing "arrayName", it will simply return the value of that variable in the global scope.
            arrayName = browser.Document.InvokeScript("eval", new object[] { "arrayName" });
    
            browser.Dispose();
            Application.ExitThread();
        };
    
        browser.Navigate(url);
    
        Application.Run();
    });
    
    // you need this when using a WebBrowser control in a console app
    thread.SetApartmentState(ApartmentState.STA);
    thread.Start();
    thread.Join();
    
    // now you should have something stored in the arrayName variable
    

    【讨论】:

    • 每次收到请求时我都需要抓取这些数据,所以我认为网络浏览器控制权重过大。理想情况下,我想要一种像 HTML 一样导航 javascript 的方法,如果不是,我认为它必须是正则表达式或类似的东西。
    • 如果性能是一个问题,然后尝试使用像 jint 这样的 Javascript 解释器来评估您使用脚本标签选择器找到的代码。
    • 我对 jint 进行了简要介绍,但文档很简短,我看不到将所有脚本放入其中并进行 eval 的简单方法。我再看看是否可以在网上找到一些示例。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-25
    • 1970-01-01
    • 1970-01-01
    • 2012-04-20
    • 1970-01-01
    • 2020-11-17
    • 1970-01-01
    相关资源
    最近更新 更多