50
4

9 回答 9

96

我建议在正则表达式上使用 HTML 解析器,但这里仍然是一个正则表达式,它将在href每个链接的属性值上创建一个捕获组。它将匹配是否使用双引号或单引号。

<a\s+(?:[^>]*?\s+)?href=(["'])(.*?)\1

您可以在此处查看此正则表达式的完整说明。

片段操场:

const linkRx = /<a\s+(?:[^>]*?\s+)?href=(["'])(.*?)\1/;
const textToMatchInput = document.querySelector('[name=textToMatch]');

document.querySelector('button').addEventListener('click', () => {
  console.log(textToMatchInput.value.match(linkRx));
});
<label>
  Text to match:
  <input type="text" name="textToMatch" value='<a href="google.com"'>
  
  <button>Match</button>
 </label>

于 2013-04-10T12:49:32.487 回答
13

regex不推荐使用解析html

regex用于定期出现的模式。html它的格式不规则(除了xhtml)。例如html,即使您没有closing tag! 这可能会破坏您的代码,文件也是有效的。

使用像htmlagilitypack这样的 html 解析器

您可以使用此代码检索href's锚标记中的所有内容HtmlAgilityPack

HtmlDocument doc = new HtmlDocument();
doc.Load(yourStream);

var hrefList = doc.DocumentNode.SelectNodes("//a")
                  .Select(p => p.GetAttributeValue("href", "not found"))
                  .ToList();

hrefList包含所有href`s

于 2013-04-10T12:57:47.223 回答
10

谢谢大家(特别是@plalx)

我发现用如此复杂和神秘的模式强制 href 属性的有效性是非常过分的,而一个简单的表达式 就足以捕获所有 URL。如果您想确保它们至少包含一个查询字符串,您可以使用
<a\s+(?:[^>]*?\s+)?href="([^"]*)"

<a\s+(?:[^>]*?\s+)?href="([^"]+\?[^"]+)"


我的最终正则表达式字符串:


首先使用其中一个:
st = @"((www\.|https?|ftp|gopher|telnet|file|notes|ms-help):((//)|(\\\\))+ \w\d:#@%/;$()~_?\+-=\\\.&]*)";
st = @"<a href[^>]*>(.*?)</a>";
st = @"((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)";
st = @"((?:(?:https?|ftp|gopher|telnet|file|notes|ms-help):(?://|\\\\)(?:www\.)?|www\.)[\w\d:#@%/;$()~_?\+,\-=\\.&]+)";
st = @"(?:(?:https?|ftp|gopher|telnet|file|notes|ms-help):(?://|\\\\)(?:www\.)?|www\.)";
st = @"(((https?|ftp|gopher|telnet|file|notes|ms-help):((//)|(\\\\))+)|(www\.)[\w\d:#@%/;$()~_?\+-=\\\.&]*)";
st = @"href=[""'](?<url>(http|https)://[^/]*?\.(com|org|net|gov))(/.*)?[""']";
st = @"(<a.*?>.*?</a>)";
st = @"(?:hrefs*=)(?:[s""']*)(?!#|mailto|location.|javascript|.*css|.*this.)(?.*?)(?:[s>""'])";
st = @"http://([\\w+?\\.\\w+])+([a-zA-Z0-9\\~\\!\\@\\#\\$\\%\\^\\&amp;\\*\\(\\)_\\-\\=\\+\\\\\\/\\?\\.\\:\\;\\'\\,]*)?";
st = @"http(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?";
st = @"(http|https)://([a-zA-Z0-9\\~\\!\\@\\#\\$\\%\\^\\&amp;\\*\\(\\)_\\-\\=\\+\\\\\\/\\?\\.\\:\\;\\'\\,]*)?";
st = @"((http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?)";
st = @"http://([\\w+?\\.\\w+])+([a-zA-Z0-9\\~\\!\\@\\#\\$\\%\\^\\&amp;\\*\\(\\)_\\-\\=\\+\\\\\\/\\?\\.\\:\\;\\'\\,]*)?";
st = @"http(s?)\:\/\/[0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*(:(0-9)*)*(\/?)([a-zA-Z0-9\-\.\?\,\'\/\\\+&amp;%\$#_]*)?$";
st = @"(?<Protocol>\w+):\/\/(?<Domain>[\w.]+\/?)\S*";

我的选择是

@"(?<Protocol>\w+):\/\/(?<Domain>[\w.]+\/?)\S*"

第二使用这个:

st = "(.*)?(.*)=(.*)";


问题解决了。感谢大家 :)

于 2013-04-21T06:15:10.093 回答
7

尝试这个 :

 public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            var res = Find(html);
        }

        public static List<LinkItem> Find(string file)
        {
            List<LinkItem> list = new List<LinkItem>();

            // 1.
            // Find all matches in file.
            MatchCollection m1 = Regex.Matches(file, @"(<a.*?>.*?</a>)",
                RegexOptions.Singleline);

            // 2.
            // Loop over each match.
            foreach (Match m in m1)
            {
                string value = m.Groups[1].Value;
                LinkItem i = new LinkItem();

                // 3.
                // Get href attribute.
                Match m2 = Regex.Match(value, @"href=\""(.*?)\""",
                RegexOptions.Singleline);
                if (m2.Success)
                {
                    i.Href = m2.Groups[1].Value;
                }

                // 4.
                // Remove inner tags from text.
                string t = Regex.Replace(value, @"\s*<.*?>\s*", "",
                RegexOptions.Singleline);
                i.Text = t;

                list.Add(i);
            }
            return list;
        }

        public struct LinkItem
        {
            public string Href;
            public string Text;

            public override string ToString()
            {
                return Href + "\n\t" + Text;
            }
        }

    }  

输入:

  string html = "<a href=\"www.aaa.xx/xx.zz?id=xxxx&name=xxxx\" ....></a> 2.<a href=\"http://www.aaa.xx/xx.zz?id=xxxx&name=xxxx\" ....></a> "; 

结果:

[0] = {www.aaa.xx/xx.zz?id=xxxx&name=xxxx}
[1] = {http://www.aaa.xx/xx.zz?id=xxxx&name=xxxx}

C# 抓取 HTML 链接

抓取 HTML 会提取重要的页面元素。它对网站管理员和 ASP.NET 开发人员有许多合法用途。使用 Regex 类型和 WebClient,我们为 HTML 实现屏幕抓取。

已编辑

另一种简单的方法:您可以使用web browser控件href从标签获取a,如下所示:(参见我的示例)

 public Form1()
        {
            InitializeComponent();
            webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser1_DocumentCompleted);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            webBrowser1.DocumentText = "<a href=\"www.aaa.xx/xx.zz?id=xxxx&name=xxxx\" ....></a><a href=\"http://www.aaa.xx/xx.zz?id=xxxx&name=xxxx\" ....></a><a href=\"https://www.aaa.xx/xx.zz?id=xxxx&name=xxxx\" ....></a><a href=\"www.aaa.xx/xx.zz/xxx\" ....></a>";
        }

        void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            List<string> href = new List<string>();
            foreach (HtmlElement el in webBrowser1.Document.GetElementsByTagName("a"))
            {
                href.Add(el.GetAttribute("href"));
            }
        }
于 2013-04-10T12:55:43.523 回答
4

试试这个正则表达式:

"href\\s*=\\s*(?:\"(?<1>[^\"]*)\"|(?<1>\\S+))"

您将从以下讨论中获得更多帮助:

从 HTML 链接中提取 URL 的正则表达式

正则表达式以获取 href 中的链接。[asp.net]

希望它有帮助。

于 2013-04-10T12:45:55.920 回答
3

我想出了这个,它支持锚和图像标签,并支持单引号和双引号。

<[a|img]+\\s+(?:[^>]*?\\s+)?[src|href]+=[\"']([^\"']*)['\"]

所以

<a href="/something.ext">click here</a>

将匹配:

 Match 1: /something.ext

<a href='/something.ext'>click here</a>

将匹配:

 Match 1: /something.ext

img src 属性也是如此

于 2016-05-10T15:56:04.610 回答
3
 HTMLDocument DOC = this.MySuperBrowser.Document as HTMLDocument;
 public IHTMLAnchorElement imageElementHref;
 imageElementHref = DOC.getElementById("idfirsticonhref") as IHTMLAnchorElement;

只需尝试此代码

于 2015-12-02T09:31:34.690 回答
0

我采取了一种更简单的方法。这只是简单地查找 href 属性,并将其后面的值(在撇号之间)捕获到一个名为 url 的组中:

href=['"](?<url>.*?)['"]

于 2021-12-09T08:32:37.077 回答
0

我认为在这种情况下,这是最简单的预赛之一

/<a\s*(.*?id[^"]*")/g

获取地址中带有变量id的链接

href开始,包括它,获取所有字符/符号(。 - 不包括换行符)直到第一个id出现,包括它,然后所有符号到最近的下一个 " 符号 ([^"]*)

于 2022-02-25T11:21:18.667 回答