Not getting correct data from span

青春壹個敷衍的年華 提交于 2019-12-13 05:19:27

问题


I've been making a custom user handler for Jessecar's SteamBot, which is unrelated to the problem I'm having, but essentially what I've done, is I've made it so you can set the bot to play a specific game by App ID, and I've been using this to idle on games for Steam Trading Cards, the only issue is, the only way I can check if it's finished, is by checking its inventory and how many cards are supposed to drop, which isn't too much of a hassle, but the main reason I created this was for efficiency, and doing this every time kind of defeats the purpose of it.

Because of this, I tried getting data from the badge page for the bot on the game that it's playing, this is what I have so far...

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.");
            }

Getting the hours works fine, if the bot has no time on that game, it doesn't appear, so I just check if it's empty then set it to 0.0, however, with the cards, it appears as either "No card drops remaining" or " card drops remaining" which it doesn't get either, I tried using the same method as the hours and only get it if it's a number, and it still returns with "0", same result goes for this...

I also tried again with doing a check if the string is empty, because that could mean there is no card drops remaining, as there would be no numbers, and I also had a look online for methods of getting span data inside a div, or span data general, and neither methods worked, they'd just return with "0". And if you can't already tell, I do have the HTML Agility Pack.


回答1:


So building in my previous answer, that I have decided not to edit, since the followup here is gonna be large. I amusing both Selenium and Html Agility Pack for this. First I log in using Selenium(I am using Mono btw). After that I type in authorize my pc manually(if yours is already authorized then skip this step) and then go to the console and press any key to proceed with getting card info. I will gather the card info for all games in this case. I can't identify which game still has card drops as it has not been implemented yet.

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);
        }
    }
}

}

The output in my case

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

This code also gives you the badge progress. You must figure out yourself how to filter your data in Html Agility Pack(read up on xpath). I also recommend that you use Selenium, since you can start a steamgame from your webpage using it.

remember that the xpath I gave you in my first answer and is also used in the code above finds ALL("//") the that has a class that equals "progress_info_bold".




回答2:


You need to be more specific about what nodes to pick. I highly disencourage you from ever using regex to try and navigate the innertext or innerhtml of an htmldocument. To find the HTmlNodes regarding if there is anymore cards to drop. try using this xpath:

"//span[@class='progress_info_bold']"

These nodes will either contain the text:

"No card drops remaining"

or

number+" card drops remaining"



来源:https://stackoverflow.com/questions/33730335/not-getting-correct-data-from-span

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!