Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 无法从span获取正确的数据_C#_Html Agility Pack - Fatal编程技术网

C# 无法从span获取正确的数据

C# 无法从span获取正确的数据,c#,html-agility-pack,C#,Html Agility Pack,我一直在为Jessecar的SteamBot制作一个自定义用户处理程序,这与我遇到的问题无关,但本质上我所做的是,我已经制作好了,这样你就可以通过应用程序ID设置机器人来玩特定的游戏,我一直在使用它来闲置Steam交易卡的游戏,唯一的问题是,我可以检查它是否完成,是通过检查它的库存和应该丢弃多少张卡,这不是一件太麻烦的事,但我创建这张卡的主要原因是为了效率,每次这样做都会有点违背它的目的 正因为如此,我尝试从游戏中机器人的徽章页面获取数据,这就是我目前所拥有的 else if (message.

我一直在为Jessecar的SteamBot制作一个自定义用户处理程序,这与我遇到的问题无关,但本质上我所做的是,我已经制作好了,这样你就可以通过应用程序ID设置机器人来玩特定的游戏,我一直在使用它来闲置Steam交易卡的游戏,唯一的问题是,我可以检查它是否完成,是通过检查它的库存和应该丢弃多少张卡,这不是一件太麻烦的事,但我创建这张卡的主要原因是为了效率,每次这样做都会有点违背它的目的

正因为如此,我尝试从游戏中机器人的徽章页面获取数据,这就是我目前所拥有的

else if (message.StartsWith(".updateidle"))
            {
                var webGet = new HtmlWeb();
                var SteamID64 = Bot.SteamClient.SteamID.ConvertToUInt64();
                string htmlget = "http://www.steamcommunity.com/profiles/" + SteamID64 + "/gamecards/" + newgame;
                var doc = webGet.Load(htmlget);

                HtmlNode hoursNode = doc.DocumentNode.SelectSingleNode("//div[@class=\"badge_title_stats_playtime\"]");
                string hours = Regex.Match(hoursNode.InnerText, @"[0-9\.,]+").Value;

                var cards = doc.DocumentNode.SelectSingleNode("div[@class='badge_title_stats_drops']/span").InnerText;



                if (hours == string.Empty)
                {
                    hours = "0.0";
                }

                Bot.SteamFriends.SendChatMessage(OtherSID, type, "I have been idling for " + hours + " hours on game " + newgame + " and have " + cards + " card drops remaining.");
            }
获取时间很好,如果机器人在游戏中没有时间,它就不会出现,因此我只需检查它是否为空,然后将其设置为0.0,然而,对于卡,它显示为“没有剩余的卡掉落”或“剩余的卡掉落”,但它也没有得到,我尝试使用与小时相同的方法,仅当它是一个数字时才获取它,它仍然返回“0”,同样的结果也适用于这个


我还再次尝试检查字符串是否为空,因为这可能意味着没有剩余的卡片丢弃,因为没有数字,我还在线查看了获取div中的span数据的方法,或者span data general,这两种方法都不起作用,它们只返回“0”。如果您还不知道,我有HTML敏捷包。

您需要更具体地选择哪些节点。我强烈建议您不要使用正则表达式来尝试导航htmldocument的innertext或innerhtml。 查找HTmlNodes,了解是否还有牌要丢。尝试使用以下xpath:

"//span[@class='progress_info_bold']"
这些节点将包含以下文本:

“没有剩余的卡掉落”


number+“card drops remaining”

因此,在我之前的回答中,我决定不进行编辑,因为这里的后续内容会很大。我觉得Selenium和Html敏捷包都很有趣。首先,我使用Selenium登录(我使用的是Mono btw)。之后,我手动输入授权我的电脑(如果您的电脑已经授权,则跳过此步骤),然后转到控制台并按任意键继续获取卡信息。在这种情况下,我将收集所有游戏的卡信息。我不能确定哪个游戏仍然有牌下降,因为它尚未实施

class MainClass
{


    public static void Main(string[] args)
    {
        string userName = "username";
        string password ="password";
        string steamProfile = "steamprofile";
        HtmlAgilityPack.HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument();


        using (var driver = new FirefoxDriver())
        {

            // Go to the home page
            driver.Navigate().GoToUrl("https://store.steampowered.com//login/?redir=0");

            // Get the page elements
            var userNameField = driver.FindElementById("input_username");
            var userPasswordField = driver.FindElementById("input_password");
            //var loginButton = driver.FindElementById("login_btn_signin");
            var loginButton = driver.FindElementByXPath("//button[@class='btnv6_blue_hoverfade  btn_medium']");

            // Type user name and password
            userNameField.SendKeys(userName);
            userPasswordField.SendKeys(password);

            // and click the login button
            loginButton.Click();
            System.Threading.Thread.Sleep(5000);

            //Type authorization code and enter manually.

            System.Console.ReadKey();

            driver.Navigate().GoToUrl("http://steamcommunity.com/profiles/"+steamProfile+"/badges");


            driver.GetScreenshot().SaveAsFile(@"screen.png", ImageFormat.Png); //Debuggin purposes, as I was first using PhantomJS


            htmlDoc.LoadHtml(driver.PageSource);

            Console.Clear();

        }

        HtmlNodeCollection col = htmlDoc.DocumentNode.SelectNodes("//span[@class='progress_info_bold']");

        foreach (HtmlNode n in col)
        {
            Console.WriteLine(n.InnerText);
        }
    }
}
}

我的案例中的输出

5 of 29 tasks completed
No card drops remaining
No card drops remaining
No card drops remaining
4 card drops remaining
3 card drops remaining
此代码还提供徽章进度。您必须弄清楚如何在Html Agility Pack中过滤数据(请阅读)。我还建议您使用Selenium,因为您可以使用它从您的网页启动一个steamgame


请记住,我在第一个答案中给出的xpath,也用于上面的代码中,它找到了所有(“/”)类,这些类的值等于“progress\u info\u bold”。

当我使用该xpath而不是我问题中的xpath时,我会收到一个错误:“System.NullReferenceException:对象引用未设置为对象的实例”而不是仅仅返回“0”。我在过去遇到过这个错误,并认为这是因为我的xpath不正确,因此我在问题中没有提到它。这表明我犯了一个错误。我两小时后下班。然后我会给你一些工作代码。你登录了吗?除非您登录该网站,否则您将无法获得正确的HtmlDocument。如果你没有,那么你就无法获得剩余的卡数。是的,如果它没有登录,我就没有时间了。已经有一个开源程序,可以通过SteamBot实现多个帐户,这允许我仍然使用我的主帐户。我尝试过这种方法,因为每次都需要Steam Guard,所以它不起作用,我没有为它设置cookie配置文件,但我意识到,当我之前获得网页时,机器人实际上没有登录到网站,这就是为什么它只获得小时数。我可以在SteamBot中获取cookies,但是有没有一种方法可以使用cookies执行HtmlDocument.Load()?我已经尝试过了,但是失败了,这里的一些人做了一个尝试,他扩展了WebClient和Browser类。我不知道它是否有效(如果有效,请报告。如果您使用Selenium,您不必担心Cookie,Selenium会为您这样做。因此,我尝试了很多方法来尝试使其有效,首先我尝试了使用HtmlWeb.Load()的原始方法但在cookies中,我还使用Selenium Firefox WebDriver测试了您的方法,它无法按照SteamGuard的要求工作,在浏览器中输入它时,它不会重定向到所需的位置进行web刮取。我在网上读到,您可以为它设置配置文件,我没有读太多,因为我认为这是一个麻烦和麻烦的问题回到HTML Agility Pack,它不再比你的方法有效,所以我决定回到Selenium方法。当我尝试使用Selenium方法时,我尝试添加sessionid、steamlogin和steamloginsecure cookies,这些cookies仍然需要SteamGuard,所以我决定研究向Firefox添加配置文件,并在这些程序用于阻止SteamGuard,但从您引用的站点登录,当重定向到我想要从中抓取网页的所需URL时,它将再次注销,因此我编辑了它在浏览器启动时进入的URL,以便在它登录后,它将直接重新指向游戏的徽章页面,这将阻止不要让它退出。