从c#中解析为html的电子邮件中获取特定的href值或链接

时间:2017-12-07 06:39:09

标签: c# html html-email exchangewebservices html-agility-pack

我正在处理C#服务中的电子邮件。我需要提取存在于其中的某些链接以添加到DB。我正在使用HtmlagilityPack。 div和p标签在解析的电子邮件中可以互换。我必须从电子邮件中提取标签“Scheduler Link”,“Data Path”和“Link”下面的链接。清理后,样本数据如下:

<html>
 <body>
   ......//contains some other tags which i dont need, may include hrefs but 
         //i dont need them 
   <div align="justify" style="margin:0;"></div>
   <div align="justify" style="margin:0;"></div>
   <div align="justify" style="margin:0;">Scheduler link :</div>
   <div align="justify" style="margin:0;"></div>
   <div style="margin:0;"><a href="https://something.com/requests/26428"> 
   https://something.com/requests/26428</a>
   </div>
   <div style="margin:0;"></div>
   <div style="margin:0;"></div>
   <div style="margin:0;"></div>
   <div align="justify" style="margin:0;">Data path :</div>
   <div align="left" style="text-align:justify;margin:0;"><a  
   href="file:///\\mycompany.com\ABC\OPQ1234\jui\tui245.5t_2rtfg_tyui"> 
   \\mycompany.com\ABC\OPQ1234\jui\tui245.5t_2rtfg_tyui</a>
   </div>
   <div align="left" style="text-align:justify;margin:0;"><a  
   href="file:///\\mycompany.com\ABC\OPQ1234\tui245.5t_2rtfg_tyui"> 
   \\mycompany.com\ABC\OPQ1234\tui245.5t_2rtfg_tyui</a>
   </div>
   <div align="justify" style="margin:0;"></div>
   <div align="justify" style="margin:0;">Link :</div>
   <div align="justify" style="margin:0;"><a 
   href="https://Thisisanotherlink.abcdef/sites/this/498592/rkjfb/3874y">
   This is some text</a></div>
   <div align="justify" style="margin:0 0 5pt 0;">This is another text</div>

   ......//contains some other tags which i dont need 
 </body>
</html>

我正在使用正则表达式查找“​​Scheduler Link”,“Data Path”和“Link”的div标签,如下所示:

HtmlNode schedulerLink = doc.DocumentNode.SelectSingleNode("//*[text()[contains(.,'" + Regex.Match(body, _keyValuePairs["scheduler"]).Value.ToString() + "')]]");
HtmlNode dataPath = doc.DocumentNode.SelectSingleNode("//*[text()[contains(.,'" + Regex.Match(body, _keyValuePairs["datapath"]).Value.ToString() + "')]]");
HtmlNode link = doc.DocumentNode.SelectSingleNode("//*[text()[contains(.,'" + Regex.Match(body, _keyValuePairs["link"]).Value.ToString() + "')]]");

div标签正在返回各自的节点。每封电子邮件中三个链接的数量不同,标签的顺序也不同。我需要在列表中捕获每个链接。我使用以下代码:

 foreach (HtmlNode link in schedulerLink.Descendants())
        {
        string hrefValue = link.GetAttributeValue("href", string.Empty);     

            if (!(link.InnerText.Contains("\r\n")))
            {
                if (link.InnerText.Contains("/"))
                {
                    schedulersList.Add(link.InnerText.Trim());
                }
            }
        }

后代有时没有返回正确数量的节点。另外,我如何获得3个不同列表中3个标签的特定链接,因为后代通常会返回下面的所有节点。

2 个答案:

答案 0 :(得分:0)

正如您在提问中提到的不同的href一样,

这样做的一种方法是:

   var html = @"<html> <body> <div align='justify' style='margin:0;'></div> <div align='justify' style='margin:0;'></div> <div align='justify' style='margin:0;'>Scheduler link :</div> <div align='justify' style='margin:0;'></div> <div style='margin:0;'><a href='https://something.com/requests/26428'> https://something.com/requests/26428</a> </div> <div style='margin:0;'></div> <div style='margin:0;'></div> <div style='margin:0;'></div> <div align='justify' style='margin:0;'>Data path :</div> <div align='left' style='text-align:justify;margin:0;'><a href='file:///\\mycompany.com\ABC\OPQ1234\jui\tui245.5t_2rtfg_tyui'> \\mycompany.com\ABC\OPQ1234\jui\tui245.5t_2rtfg_tyui</a> </div> <div align='left' style='text-align:justify;margin:0;'><a href='file:///\\mycompany.com\ABC\OPQ1234\tui245.5t_2rtfg_tyui'> \\mycompany.com\ABC\OPQ1234\tui245.5t_2rtfg_tyui</a> </div> <div align='justify' style='margin:0;'></div> <div align='justify' style='margin:0;'>Link :</div> <div align='justify' style='margin:0;'><a href='https://Thisisanotherlink.abcdef/sites/this/498592/rkjfb/3874y'> This is some text</a></div> <div align='justify' style='margin:0 0 5pt 0;'>This is another text</div> </body></html>";
        var document = new HtmlDocument();
        document.LoadHtml(html);

        var schedulerNodes = document.DocumentNode.SelectNodes("//a[contains(@href, \"something\")]");
        var dataPathNodes = document.DocumentNode.SelectNodes("//a[contains(@href, \"mycompany\")]");
        var linkNodes = document.DocumentNode.SelectNodes("//a[contains(@href, \"Thisisanotherlink\")]");

        foreach (var item in schedulerNodes)
        {
            Debug.WriteLine(item.GetAttributeValue("href", ""));
            Debug.WriteLine(item.InnerText);
        }
        foreach (var item in dataPathNodes)
        {
            Debug.WriteLine(item.GetAttributeValue("href", ""));
            Debug.WriteLine(item.InnerText);
        }
        foreach (var item in linkNodes)
        {
            Debug.WriteLine(item.GetAttributeValue("href", ""));
            Debug.WriteLine(item.InnerText);
        }

希望有所帮助!!

编辑::

    var result = document.DocumentNode.SelectNodes("//div//text()[normalize-space()] | //a");
// select all textnodes and a tags
            string sch = "Scheduler link :";
            string dataLink = "Data path :";
            string linkpath = "Link :";
            foreach (var item in result)
            {
                if (item.InnerText.Trim().Contains(sch))
                {
                        var processResult = result.SkipWhile(x => !x.InnerText.Trim().Equals(sch)).Skip(1);
// skip the result till we reache to Scheduler.
                        Debug.WriteLine("====================Scheduler link=========================");
                        foreach (var subitem in processResult)
                        {
                            Debug.WriteLine(subitem.GetAttributeValue("href", ""));
// if href then add to list TODO
                            if (subitem.InnerText.Contains(dataLink)) // break when data link appears.
                            {
                                break;
                            }
                        }
                    }
                    if (item.InnerText.Trim().Contains(dataLink))
                    {
                        var processResult = result.SkipWhile(x => !x.InnerText.Trim().Equals(dataLink)).Skip(1);
                        Debug.WriteLine("====================Data link=========================");

                        foreach (var subitem in processResult)
                        {
                            Debug.WriteLine(subitem.GetAttributeValue("href", ""));
                            if (subitem.InnerText.Contains(dataLink))
                            {
                                break;
                            }
                        }
                    }
                    if (item.InnerText.Trim().Contains("Link :"))
                    {
                        var processResult = result.SkipWhile(x => !x.InnerText.Trim().Equals(linkpath)).Skip(1);
                        Debug.WriteLine("====================Link=========================");
                        foreach (var subitem in processResult)
                        {
                            var hrefValue = subitem.GetAttributeValue("href", "");
                            Debug.WriteLine(hrefValue);
                            if (subitem.InnerText.Contains(dataLink))
                            {
                                break;
                            }
                        }
                    }
                }

我在代码提交中提到了逻辑。

希望有所帮助

答案 1 :(得分:0)

如果我理解正确,您希望在特定字符串scheduler link之后捕获第一个href属性的内容。我不知道HtmlagilityPack,但我的方法是只用这样的正则表达式搜索电子邮件正文:

Scheduler link(?:\s|\S)*?href="([^"]+)

此正则表达式应该在邮件中每次出现“调度程序链接”后捕获第一个href属性的内容。

您可以在此处试用:Regex101

要查找其他类型的链接,只需将Scheduler link部分替换为相应的字符串。

我希望这有用。

有关正则表达式的其他信息:

  • Scheduler link字面上匹配字符串
  • (?:\s|\S)*?href="匹配任何字符的非捕获组,直到第一次出现文字字符串href="
  • ([^"]+)捕获了"字符
  • 的所有内容