使用Htmlagilitypack加载多个页面-C#

时间:2019-04-22 17:41:34

标签: c# html html-agility-pack

我用C#刮擦了一个带有HTMLAgilityPack的网站,我试图打开其中的所有链接,并用相同的方法刮擦它们。 但是,当我尝试在底部调用此方法时,由于我激活了AdBlock,因此页面是从库中下载的。实际上,我找不到任何表格,下载的HTML代码显示“ ADblock found”。 这很奇怪,因为我已经在我的Google Chrome浏览器中过滤了oddsmath网站,并且可以毫无问题地下载母版页。有人遇到过这个问题吗?

这是函数,“ Console.WriteLine”仅用于测试并查看完整的HTML代码。

<div class="checkbox-password">
    <div class="remember-me">
       <mat-checkbox class="example-margin">Remember me</mat-checkbox>
    </div>
    <div>
       <a routerLink="/forgotPassword" class="createAccount" 
                routerLinkActive="active"> Forgot Password? </a>
   </div>

编辑 更深入一点,我注意到这可能不是我的应用程序问题或与Adblock相关的问题,但似乎连接到我要抓取的网站...实际上,如果您看到这样的页面:奇怪。 com / football / international / afc-champions-league-1053 /…,您可以看到内容已在浏览器中正确加载,但表在源代码中为空。为什么?是Javascript阻止了页面加载吗?

1 个答案:

答案 0 :(得分:1)

首先:使用最适合HAP vs AngleSharp的东西,除非时间确实是应用程序中的一个因素。在这种情况下不是。

第二:使用Web调试器(例如Fiddler或Charles)来了解发出请求时的实际含义。由于您实际上并没有使用javascript或api调用创建任何html。您仅获得页面源。这就是为什么表为空的原因。它们是使用javascript生成的。

例如。我只是使用网络调试器来查看该网站对以下内容进行了api调用:

http://www.oddsmath.com/api/v1/dropping-odds.json/?sport_type=soccer&provider_id=7&cat_id=0&interval=60&sortBy=1&limit=30&language=en

然后javascript将使用此json对象创建页面的其余部分。

这将返回一个不错的json对象,该对象比使用eithr HAP或AngleSharp的导航更容易。我建议使用NewtonSoft JSON。

如果您坚持使用HtmlAgilityPack,则需要将其与Selenium结合使用。因为那样您可以等到页面完全加载后再解析HTML。

[编辑] 进一步挖掘:

Api要求获取所有联赛及其ID:

http://www.oddsmath.com/api/v1/menu-leagues.json/?language=en

仅要求亚洲冠军联赛的api:

http://www.oddsmath.com/api/v1/events-by-league.json/?language=en&country_code=GB&league_id=1053

带有Firefox驱动程序的Selenium的其他解决方案。

虽然我强烈建议您在解决方案中使用API​​和NewtonSoft-JSON,但我将提供如何使用Selenium来完成。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HtmlAgilityPack;
using OpenQA.Selenium.Firefox;
using OpenQA.Selenium;
using System.Threading;

namespace SeleniumHap {
    class Program {
        static void Main(string[] args)
        {
            HtmlDocument doc = new HtmlDocument();
            string url = "http://www.oddsmath.com/football/sweden/division-1-1195/2019-04-26/if-sylvia-vs-nykopings-bis-2858046/";
            //string url = "http://www.oddsmath.com/";

            FirefoxOptions options = new FirefoxOptions();
            //options.AddArguments("--headless");
            IWebDriver driver = new FirefoxDriver(options);
            driver.Navigate().GoToUrl(url);
            while (true) {
                doc.LoadHtml(driver.PageSource);
                HtmlNode n = doc.DocumentNode.SelectSingleNode("//table[@id='table-odds-cat-0']//*[self::th or self::td]");
                if (n != null) {
                    n = n.SelectSingleNode(".//div[@class='live-odds-loading']");
                    if (n == null) {
                        break;
                    }
                }
                Thread.Sleep(1000);
            }
            Console.WriteLine("Exited loop. Meaning the page is done loading since we could get a td. A Crude method but it works");

            HtmlNodeCollection tables = doc.DocumentNode.SelectNodes("//table");

            foreach(HtmlNode table in tables) {
                Console.WriteLine(table.GetAttributeValue("id", "No id"));
                HtmlNodeCollection tableContent = table.SelectNodes(".//*[self::th or self::td]");
                foreach(HtmlNode n in tableContent) {
                    Console.WriteLine(n.InnerHtml);
                }
                break;
            }

            Console.ReadKey();
        }
    }
}

如您所见,我使用Firefox作为我的驱动程序而不是chrome。使用这两种方法时,您可能必须在编辑变量'BrowserExecutableLocation'的位置编辑选项,以告知浏览器的可执行文件在哪里。 如您所见,我正在以一种粗略的方式使用while循环,以确保浏览器在继续阅读html之前完全加载了页面。