【问题标题】:Get substring in C# from the html?从 html 获取 C# 中的子字符串?
【发布时间】:2020-04-07 16:37:12
【问题描述】:

我有一个页面需要获取子字符串,所以我编写了以下代码:

static string GetBetween(string message, string start, string end)
        {
            int startIndex = message.IndexOf(start) + start.Length;
            int stopIndex = message.IndexOf(end);
            return message.Substring(startIndex, stopIndex - startIndex);

        }

这是获取值的代码:

 string myStr = HttpMethods.Get("https://www.marktplaats.nl/account/login.html", "https://www.marktplaats.nl/account/login.html", ref myCookies);
            string myToken;
            Console.WriteLine("Token: " + (myToken = GetBetween(myStr, "name='xsrf.token' value='", "'>")));

但不是获取此行之间的值(每次执行新 WebRequest 时值都会更改,因此我每次都需要获取新值):

<input type="hidden" name="xsrf.token" value="1576329716873.d7a4f9a4b3f8e63fa5d1fe94730774c34b327ec96cdbb4aaca405de3b96231b3(THIS CHANGES EVERYTIME I LOAD THE PAGE)">

它给了我这个输出:

ng="nl">
<head>
    <title>= Marktplaats - De plek om nieuwe en tweedehands spullen te kopen en verkopen</title>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta http-equiv="Content-Language" content="nl">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="De grootste advertentiesite van Nederland. Nieuwe en tweedehands goederen en diensten, koopt en verkoopt u op Marktplaats.nl.">
    <link rel="shortcut icon" href="//s.marktplaats.com/static-web/identity/vendor/design-sdk/themes/mp/favicons/favicon.3e02874c.ico">
    <link rel="apple-touch-icon" sizes="57x57" href="//s.marktplaats.com/static-web/identity/vendor/design-sdk/themes/mp/favicons/apple-touch-icon-57x57.722d5557.png">
    <link rel="apple-touch-icon" sizes="114x114" href="//s.marktplaats.com/static-web/identity/vendor/design-sdk/themes/mp/favicons/apple-touch-icon-114x114.fdd2bafc.png">
    <link rel="apple-touch-icon" sizes="72x72" href="//s.marktplaats.com/static-web/identity/vendor/design-sdk/themes/mp/favicons/apple-touch-icon-72x72.6af4f862.png">
    <link rel="apple-touch-icon" sizes="144x144" href="//s.marktplaats.com/static-web/identity/vendor/design-sdk/themes/mp/favicons/apple-touch-icon-144x144.319efd6c.png">
    <link rel="apple-touch-icon" sizes="60x60" href="//s.marktplaats.com/static-web/identity/vendor/design-sdk/themes/mp/favicons/apple-touch-icon-60x60.c37547f0.png">
    <link rel="apple-touch-icon" sizes="120x120" href="//s.marktplaats.com/static-web/identity/vendor/design-sdk/themes/mp/favicons/apple-touch-icon-120x120.94703796.png">
    <link rel="apple-touch-icon" sizes="76x76" href="//s.marktplaats.com/static-web/identity/vendor/design-sdk/themes/mp/favicons/apple-touch-icon-76x76.8866913d.png">
    <link rel="apple-touch-icon" sizes="152x152" href="//s.marktplaats.com/static-web/identity/vendor/design-sdk/themes/mp/favicons/apple-touch-icon-152x152.d5085224.png">
    <link rel="apple-touch-icon" sizes="180x180" href="//s.marktplaats.com/static-web/identity/vendor/design-sdk/themes/mp/favicons/apple-touch-icon-180x180.8a15fd8d.png">
    <link rel="icon" type="image/png" sizes="192x192" href="//s.marktplaats.com/static-web/identity/vendor/design-sdk/themes/mp/favicons/favicon-192x192.da693c37.png">
    <link rel="icon" type="image/png" sizes="160x160" href="//s.marktplaats.com/static-web/identity/vendor/design-sdk/themes/mp/favicons/favicon-160x160.a3b4d12c.png">
    <link rel="icon" type="image/png" sizes="96x96" href="//s.marktplaats.com/static-web/identity/vendor/design-sdk/themes/mp/favicons/favicon-96x96.cc0ba841.png">
    <link rel="icon" type="image/png" sizes="16x16" href="//s.marktplaats.com/static-web/identity/vendor/design-sdk/themes/mp/favicons/favicon-16x16.ce3b2c65.png">
    <link rel="icon" type="image/png" sizes="32x32" href="//s.marktplaats.com/static-web/identity/vendor/design-sdk/themes/mp/favicons/favicon-32x32.595f2e60.png">
    <meta name="theme-color" content="#eda566">
    <meta name="msapplication-TileColor" content="#eda566">
    <meta name="msapplication-square150x150logo" content="//s.marktplaats.com/static-web/identity/vendor/design-sdk/themes/mp/favicons/mstile-150x150.e3e83679.png">
    <meta name="msapplication-square310x310logo" content="//s.marktplaats.com/static-web/identity/vendor/design-sdk/themes/mp/favicons/mstile-310x310.09da1373.png">
    <meta name="msapplication-square70x70logo" content="//s.marktplaats.com/static-web/identity/vendor/design-sdk/themes/mp/favicons/mstile-70x70.2bc50495.png">
    <meta name="msapplication-wide310x150logo" content="//s.marktplaats.com/static-web/identity/vendor/design-sdk/themes/mp/favicons/mstile-310x150.80f61dab.png">
    <meta name="msapplication-config" content="none">
    <meta name="generation-time-millis" content="1576332442585">
    <meta name="user-logged-in" content="false">
    <link rel="stylesheet" type="text/css" href="//s.marktplaats.com/static-web/identity/vendor/normalize.css/normalize.112272e5.css" />
    <link rel="stylesheet" type="text/css" href="//s.marktplaats.com/static-web/identity/vendor/design-sdk/themes/mp/Index.ad7c2c53.css" />

        <script src="//s.marktplaats.com/static-web/identity/vendor/design-sdk/polyfills/polyfills.bce7e2b1.js"></script>
        <script src="//s.marktplaats.com/static-web/identity/vendor/design-sdk/components/polymer.1a8b099b.js"></script>
        <link rel="import" href="//s.marktplaats.com/static-web/identity/vendor/design-sdk/themes/mp/CssVars.d3ec1e54.html">
        <style is="custom-style" include="mp-css-vars"></style>
        <link rel="import" href="//s.marktplaats.com/static-web/identity/vendor/design-sdk/organisms/header.63727d14.html">
        <link rel="stylesheet" type="text/css" media="screen" href="//s.marktplaats.com/static-web/identity/css/Login.mp.nlnl.6f8ceda7.css"/>
    <script>
        window.dataLayer = [{"p":{"t":"Login"},"c":{"l1":{"id":-1},"l2":{"id":-1},"c":{"id":-1}},"u":{"li":false,"tg":{"stg":"aur7110_b|aur10242_a|aur6493_a|aur9628_b|aur3815-android_b|alternative-redirect_b|aur9245_a|aur9234_b|aur7712new_c|aur9777_c|aur9214_b|aur7342android_c|an-lmap_b|aur9848_b|aur9247_b|aur7377-order_b|aur8977_c|aur2445_b|aur9583_b|aur10018_a|aur9439_b|aur8030_c|aur2389_s_b|aur5496_a|vos2-150_b|aur7892_b|aur9856_b|aur9629_a|aur9007_b|vos6677_b|aur9752_a|aur10141_a|aur6760_a|aur-cdata345_a|aur10256_a|aur8865_b|aur4923_c|aur6594_a|aur5875_c|aur-cdata673_b|aur7918_b|aur3815_s_b|aur9834_b|aur8682_b|aur9749_a|aur6087_b|aur6503_a|aur8949_a|aur8950_a|aur9863_c|aur8221_b|aur8863_b|aur8808_b|aur5346_b|aur9685_b|aur8722_c|aur9555_b|pie3083-vip_a|aur6745_a|pie-2608-reblaze-challenge-tag_a|aur4627_b|aur10388_b|aur8790_b|aur8721_c|aur6916_a|aur9761_a|unsupported-browser-warning_b|aur3130_b|aur7826_b|aur9996_b|aur7464_b|aur9939_b|aur2389_v_b|aur5496-android_a|aur7958_b|aur10124_b|aur6034_a|aur2862_b|aur8869_b|aur9380_b|aur3186_b|aur8533_b|aur6207_b|aur9287v2_b|aur6768_b|aur9714_b|aur6915_a|aur10022_b|aur9187_b|aur10313_a|aur2805_b"}},"d":{"ua":"Go-http-client\u002F1.1"},"s":{"pn":-1,"ps":-1,"tr":-1,"srt":{},"prc":{"mn":-1,"mx":-1}},"l":{"d":-1},"a":{},"o":{},"m":{}}];
    </script>

        <script src="//s.marktplaats.com/static-web/identity/vendor/raven-js/raven.min.daf037c2.js" crossorigin="anonymous"></script>
        <script type="text/javascript">
            Raven.config('https://e50a08a833ea4c4f8cd6413450461127@sentry.marktplaats.nl/10', {
                release: 'nohash',
                tags: {
                    artifactId: 'identity-frontend',
                    requestId: '998712b4-8022-47fb-bcc6-d18f0c4de521'
                }
            }).install();

        </script>

    <script type='text/javascript

网站是:

https://www.marktplaats.nl/account/login.html

修复此错误后,我得到了这个,这是我的整个网络请求:

This is my method

This is my main program.cs

【问题讨论】:

  • 为什么要做大量的字符串处理?
  • @AnandVaidya 想要制作一个 UI 以更快地分享广告,所以我需要令牌才能使用我的 webrequest 登录。
  • 尝试使用 HtmlAgilitypack。记住这一点:不要正则表达式 Html 内容。尝试使用 html 解析器!
  • @Mr.D 感谢您提供的信息,我对 C# 有点陌生。你能看看我的新错误以及我的请求标头做错了什么吗?在此先感谢:)
  • Protip:停止使用字符串解析/正则表达式。查看正确解析 HTML(或使用浏览器对象来获取已经提供 DOM 遍历的浏览器对象)。例如。 stackoverflow.com/q/56107/298053

标签: c# html substring


【解决方案1】:

使用正则表达式。

string myStr = HttpMethods.Get("https://www.marktplaats.nl/account/login.html", "https://www.marktplaats.nl/account/login.html", ref myCookies);
string regex = "<input type\\=\\\"hidden\\\" name=\\\"xsrf\\.token\\\" value\\=\\\"([^\\\"]+)\\\"";

var xsrfToken = Regex.Match(myStr, regex).Groups[1].Value;

Console.WriteLine(xsrfToken);

至于那些说你永远不应该使用 Regex 来解析 HTML,使用 HTML Agility Pack 来做这样的事情是矫枉过正的,而且可能会表现得更糟,不相信我吗?从他们自己的开发人员那里听到它

https://html-agility-pack.net/knowledge-base/43677736/csharp-htmlagilitypack-vs-regular-expressions-for-extracting-links-from-html

【讨论】:

  • 我没有得到你的代码,因为每次我使用 webrequest 时,expectedOutput 都是不同的,我只需要每个新 webrequest 的值后的代码。还是谢谢
  • 是的,每次输出都不同,它应该是,但它每次抓取的文本是实际的 xsrf 令牌。您是要抢夺令牌还是要抢占整条线?如果您尝试获取令牌,请将“testCase”替换为网站的 html 输出,它将返回您正在搜索的 xsrf 令牌
  • 我每次都尝试获取令牌。我对 C# 有点陌生,并试图获取输入字段的值。您可以更改您的代码,以便我可以获取输入字段的值吗?感谢您的帮助,我非常感谢。
  • 这对我有用,但是我的 webrequest 出错了,你可以看看这个网站的请求吗?我认为我的标题有问题。我收到一个错误,上面写着字符串不是json格式的吗?在我的问题中发布了我的请求的图片。
  • @JimBerg 我明白了,问题是正在使用的示例文本,我正在测试他正在使用的网站的实际 HTML
【解决方案2】:

如果字符串start =

"name=\"xsrf.token\" value=\""

和字符串end =

"\""

然后:

static string GetBetween(string message, string start, string end)
        {
            //Required to handle possible problems that will arise due to indexing if the string does not exist
            try{

                //Splits the original message by the character array of the string "start", then takes the second index of that string array
                string splitmessage = message.Split(new string[] {start})[1]

                //Splits the remaining message by the character array of string "end", then takes the first index of that string array
                splitmessage = message.Split(new string[] {end})[0]

                return splitmessage;

            } catch(Exeption ex){
                //Handle when the string you're attempting to find is not there
            }

        }

应该只返回您正在寻找的输入值。

当没有单独找到该值时,您将不得不处理发生的情况。

【讨论】:

    【解决方案3】:

    您对 GetBetween 的调用甚至没有传递正确的值。它应该是双引号,而不是单引号,因为您正在搜索的文本使用双引号。

    您还需要通过检查索引是否小于零来验证您确实找到了字符串。

    你可以用这个:

        public static string GetBetween(string source, string start, string end)
        {
            var startPos = source.IndexOf(start, StringComparison.Ordinal);
            if (startPos < 0) return null;
            startPos += start.Length;
            var endPos = source.IndexOf(end, startPos,StringComparison.Ordinal);
            return endPos < 0 ? null : source.Substring(startPos, endPos - startPos - 1);
        }
    

    如果字符串不存在,则返回 null。

    添加基准代码供参考: 私有静态字符串检查 = "";

        static void Main(string[] args)
        {
            string regex = "<input type\\=\\\"hidden\\\" name=\\\"xsrf\\.token\\\" value\\=\\\"([^\\\"]+)\\\"";
            var reg = new Regex(regex);
            string xsrfToken;
            DateTime start;
            TimeSpan diff;
            var rnd = new Random();
    
            for (var j = 0; j < 100; j++)
            {
                if (rnd.Next(30) < 10)
                {
                    start = DateTime.Now;
                    for (var i = 0; i < 10000000; i++)
                        xsrfToken = Regex.Match(check, regex).Groups[1].Value;
                    diff = DateTime.Now - start;
                    Console.WriteLine("RegEx: " + diff.TotalSeconds);
                    continue;
                }
    
                if (rnd.Next(30) < 20)
                {
                    start = DateTime.Now;
                    for (var i = 0; i < 10000000; i++)
                        xsrfToken = reg.Match(check).Groups[1].Value;
                    diff = DateTime.Now - start;
                    Console.WriteLine("RegEx Prepped: " + diff.TotalSeconds);
                    continue;
                }
    
                start = DateTime.Now;
                for (var i = 0; i < 10000000; i++)
                    xsrfToken = InBetween(check, "name=\"xsrf.token\" value=\"", ">");
                diff = DateTime.Now - start;
                Console.WriteLine("InBetween: " + diff.TotalSeconds);
            }
    
            Console.ReadKey();
        }
    
        public static string InBetween(string source, string start, string end)
        {
            var startPos = source.IndexOf(start, StringComparison.Ordinal);
            if (startPos < 0) return null;
            startPos += start.Length;
            var endPos = source.IndexOf(end, startPos, StringComparison.Ordinal);
            return endPos < 0 ? null : source.Substring(startPos, endPos - startPos - 1);
        }
    

    【讨论】:

    • 感谢您的帮助,@Aydin 帮助了我,但我发布了一个发生的新错误。也许您可以帮助我解决这个请求?
    • @CSharper 您的问题已经得到解答。将他的答案标记为您的解决方案,以便他获得声誉积分,然后就您的其他问题提出新的问题。据我所知,这些不应该是开放的调试会话。
    猜你喜欢
    • 2013-11-07
    • 2011-05-25
    • 2012-01-26
    • 1970-01-01
    • 1970-01-01
    • 2019-01-28
    • 2011-11-05
    相关资源
    最近更新 更多