在使用HTML Agility搜索所需数据后,如何从网页中抓取数据

时间:2017-11-14 16:15:15

标签: c# html asp.net html-agility-pack

我想从this website

获取信息

使用HTML Agility Pack进入我的ASPX页面。但我不能这样做,因为在我搜索网页中的数据后加载数据。

我需要在5分钟的间隔后连续完成一些数据。

2 个答案:

答案 0 :(得分:2)

您提到的网站搜索结果是使用Javascript动态呈现的,数据来自Ajax的Json响应。 HtmlAgilityPack旨在解析Html,而不是Json。

考虑使用<nav class="navbar navbar-toggleable-md navbar-fixed-top topnav" role="navigation"> <div class="navbar-header"> <a class="navbar-brand" href="#" target="_blank" id="heading">Samrat Luitel</a> </div> <div> <ul class="navbar-nav navbar-right"> <li class="nav-item"><a href="#home" style="color:black" class="nav-link">Home</a></li> <li class="nav-item"><a href="#home" style="color:black" class="nav-link">About Us</a></li> <li class="nav-item"><a href="#home" style="color:black" class="nav-link">Contact Us</a></li> </ul> </div> </nav> Selenium驱动程序用于.Net,或iMacros类提供Microsoft Framework。这些工具在后台运行浏览器,因此他们可以在该页面中运行Javascript代码并呈现您想要抓取的Html。

只需要设置适当的超时时间,这样他们就会一直等到搜索结果出现在页面上。

答案 1 :(得分:0)

正如@derloopkat已经说过的那样。只需使用Selenium。

该网站使用javascript和ajax更新页面的HTML。即使您使用以下网址执行HTTP请求:

https://enquiry.indianrail.gov.in/ntes/NTES?action=getTrainsViaStn&viaStn=NDLS&toStn=null&withinHrs=2&trainType=ALL&6iop0ssrpi=1m1ol4ha86

您只会收到以下内容:

(function(){location.reload();/*ho ho ho ho*/})()

表示url的最后一个参数:

&6iop0ssrpi=1m1ol4ha86

是某种“密码”(缺少更好的词)。这确保您不能只重播重播请求。现在你可以尝试解决这个问题。但它在javascript文件中被模糊,这是3396行非常密集的代码。因此,找到发送服务器的内容以接收您想要的数据非常困难(甚至可能是不可能的)。

更好的是服务器的响应永远不会是HTML而是JSON。格式如下:

    _obj_1511003507337 = {
trainsInStnDataFound:"trainRunningDataFound",
allTrains:[
{
trainNo:"14316",
startDate:"18 Nov 2017",
trainName:"INTERCITY EXP",
trnName:function(){return _LANG==="en-us"?"INTERCITY EXP":"इंटरसिटीएक्स."},
trainSrc:"NDLS",
trainDstn:"BE",
runsOn:"NA",
schArr:"Source",
schDep:"16:35, 18 Nov",
schHalt:"Source",
actArr:"Source",
delayArr:"RIGHT TIME",
actDep:"16:35, 18 Nov",
delayDep:"RIGHT TIME",
actHalt:"Source",
trainType:"MEX",
pfNo:"9"
} ,
trainNo:"12625",
startDate:"16 Nov 2017",
trainName:"KERALA EXPRESS",
trnName:function() { return _LANG === "en-us" ? "KERALA EXPRESS" : "केरलएक्स."},
trainSrc:"TVC",
trainDstn:"NDLS",
runsOn:"NA",
schArr:"13:45, 18 Nov",
schDep:"Destination",
schHalt:"Destination",
actArr:"16:56, 18 Nov",
delayArr:"03:11",
actDep:"Destination",
delayDep:"RIGHT TIME",
actHalt:"Destination",
trainType:"SUF",
pfNo:"4"
} 
    ]
}

以下是使用Selenium获取HTML和数据的解决方案。

using System;
using System.Collections.Generic;
using System.Net;
using HtmlAgilityPack;
using OpenQA.Selenium.Firefox;
using OpenQA.Selenium;
using System.Threading;

namespace test
{
    class Program
    {

    public static void Main(string[] args)
    {
            string url = "https://www.google.com";
            IWebDriver driver = new FirefoxDriver();
           driver.Navigate().GoToUrl("https://enquiry.indianrail.gov.in");
            Console.WriteLine("Step 1");
            driver.FindElement(By.XPath("//a[@id='ui-id-2']")).Click();
            Thread.Sleep(10000);
            Console.WriteLine("Step 2");
            driver.FindElement(By.XPath("//input[@id='viaStation']")).SendKeys("NEW DELHI [NDLS]");
            Thread.Sleep(2000);
            Console.WriteLine("Step 3");
            driver.FindElement(By.XPath("//button[@id='viaStnGoBtn']")).Click();

            //PRESS A KEY WHEN THE HTML IS FULLY LOADED
            Console.ReadKey();



            HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
            doc.LoadHtml(driver.PageSource);

            HtmlNodeCollection nodeCol = doc.DocumentNode.SelectNodes("//body//tr[@class='altBG']");
            foreach(HtmlNode node in nodeCol){
                Console.WriteLine("Trip:");
                foreach(HtmlNode child in node.ChildNodes)
                {
                    Console.WriteLine("\t" + child.InnerText);
                }
            }
            //Console.WriteLine(doc.DocumentNode.InnerHtml);
            Console.ReadKey();

    }

Thread.Sleep()不应该是必需的。我只是把它们作为预防措施。如果您使用像PhantomJS这样的无头驱动程序,也可以优化速度。