正規表現でHTMLリンクを抽出する方法
このチュートリアルでは、HTMLページからハイパーリンクを抽出する方法を説明します。たとえば、次のコンテンツからリンクを取得するには:
this is text1 <a href='mkyong.com' target='__blank'>hello</a> this is text2...
-
まず `a`タグから” value “を取得します – 結果:
a href = 'mkyong.com' target = '__ blank'
。後で抽出された値から「リンク」を得る – 結果:
mkyong.com
1.正規表現パターン
タグを抽出する正規表現パターン
(?i)<a([^>]+)>(.+?)</a>
タグからのリンクを抽出する正規表現パターン
\s** (?i)href\s** =\s** (\"([^"]** \")|'[^']** '|([^'">\s]+));
説明
( #start of group #1 ?i # all checking are case insensive ) #end of group #1 <a #start with "<a" ( # start of group #2 [^>]+ # anything except (">"), at least one character ) # end of group #2 > # follow by ">" (.+?) # match anything </a> # end with "</a>
\s** #can start with whitespace (?i) # all checking are case insensive href # follow by "href" word \s** =\s** # allows spaces on either side of the equal sign, ( # start of group #1 "([^"]** ") # allow string with double quotes enclosed - "string" | # ..or '[^']** ' # allow string with single quotes enclosed - 'string' | # ..or ([^'">]+) # can't contains one single quotes, double quotes ">" ) # end of group #1
2. Java Link Extractorの例
ここでは単純なJava Link Extractorの例を示します。最初のパターンから `a`タグ値を抽出し、2番目のパターンを使用して1番目のパターンからリンクを抽出します。
HTMLLinkExtractor.java
package com.mkyong.crawler.core; import java.util.Vector; import java.util.regex.Matcher; import java.util.regex.Pattern; public class HTMLLinkExtractor { private Pattern patternTag, patternLink; private Matcher matcherTag, matcherLink; private static final String HTML__A__TAG__PATTERN = "(?i)<a([^>]+)>(.+?)</a>"; private static final String HTML__A__HREF__TAG__PATTERN = "\\s** (?i)href\\s** =\\s** (\"([^\"]** \")|'[^']** '|([^'\">\\s]+))"; public HTMLLinkExtractor() { patternTag = Pattern.compile(HTML__A__TAG__PATTERN); patternLink = Pattern.compile(HTML__A__HREF__TAG__PATTERN); } /** ** ** Validate html with regular expression ** ** @param html ** html content for validation ** @return Vector links and link text ** / public Vector<HtmlLink> grabHTMLLinks(final String html) { Vector<HtmlLink> result = new Vector<HtmlLink>(); matcherTag = patternTag.matcher(html); while (matcherTag.find()) { String href = matcherTag.group(1);//href String linkText = matcherTag.group(2);//link text matcherLink = patternLink.matcher(href); while (matcherLink.find()) { String link = matcherLink.group(1);//link HtmlLink obj = new HtmlLink(); obj.setLink(link); obj.setLinkText(linkText); result.add(obj); } } return result; } class HtmlLink { String link; String linkText; HtmlLink(){}; @Override public String toString() { return new StringBuffer("Link : ").append(this.link) .append(" Link Text : ").append(this.linkText).toString(); } public String getLink() { return link; } public void setLink(String link) { this.link = replaceInvalidChar(link); } public String getLinkText() { return linkText; } public void setLinkText(String linkText) { this.linkText = linkText; } private String replaceInvalidChar(String link){ link = link.replaceAll("'", ""); link = link.replaceAll("\"", ""); return link; } } }
ユニットテスト
TestNGによるユニットテスト。 `@ DataProvider`を介してHTMLコンテンツをシミュレートします。
TestHTMLLinkExtractor.java
package com.mkyong.crawler.core; import java.util.Vector; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import com.mkyong.crawler.core.HTMLLinkExtractor.HtmlLink; /** ** ** HTML link extrator Testing ** ** @author mkyong ** ** /public class TestHTMLLinkExtractor { private HTMLLinkExtractor htmlLinkExtractor; String TEST__LINK = "http://www.google.com"; @BeforeClass public void initData() { htmlLinkExtractor = new HTMLLinkExtractor(); } @DataProvider public Object[][]HTMLContentProvider() { return new Object[][]{ new Object[]{ "abc hahaha <a href='" + TEST__LINK + "'>google</a>" }, new Object[]{ "abc hahaha <a HREF='" + TEST__LINK + "'>google</a>" }, new Object[]{ "abc hahaha <A HREF='" + TEST__LINK + "'>google</A> , " + "abc hahaha <A HREF='" + TEST__LINK + "' target='__blank'>google</A>" }, new Object[]{ "abc hahaha <A HREF='" + TEST__LINK + "' target='__blank'>google</A>" }, new Object[]{ "abc hahaha <A target='__blank' HREF='" + TEST__LINK + "'>google</A>" }, new Object[]{ "abc hahaha <A target='__blank' HREF=\"" + TEST__LINK + "\">google</A>" }, new Object[]{ "abc hahaha <a HREF=" + TEST__LINK + ">google</a>" }, }; } @Test(dataProvider = "HTMLContentProvider") public void ValidHTMLLinkTest(String html) { Vector<HtmlLink> links = htmlLinkExtractor.grabHTMLLinks(html); //there must have something Assert.assertTrue(links.size() != 0); for (int i = 0; i < links.size(); i++) { HtmlLink htmlLinks = links.get(i); //System.out.println(htmlLinks); Assert.assertEquals(htmlLinks.getLink(), TEST__LINK); } } }
結果
….[TestNG]Running:
/private/var/folders/w8/jxyz5pf51lz7nmqm__hv5z5br0000gn/T/testng-eclipse—530204890/testng-customsuite.xml
PASSED: ValidHTMLLinkTest(“abc hahaha <a href=’http://www.google.com’>google</a>”)
PASSED: ValidHTMLLinkTest(“abc hahaha <a HREF=’http://www.google.com’>google</a>”)
PASSED: ValidHTMLLinkTest(“abc hahaha <A HREF=’http://www.google.com’>google</A> , abc hahaha <A HREF=’http://www.google.com’ target=’
blank’>google</A>”)
PASSED: ValidHTMLLinkTest(“abc hahaha <A HREF=’http://www.google.com’ target=’
blank’>google</A>”)
PASSED: ValidHTMLLinkTest(“abc hahaha <A target=’
blank’ HREF=’http://www.google.com’>google</A>”)
PASSED: ValidHTMLLinkTest(“abc hahaha <A target=’
blank’ HREF=”http://www.google.com”>google</A>”)
PASSED: ValidHTMLLinkTest(“abc hahaha <a HREF=http://www.google.com>google</a>”)
=== 参考文献 . http://testng.org/doc/documentation-main.html[TestNG documentation] . http://ja.wikipedia.org/wiki/Hyperlink[Hyperlink in Wiki] link://tag/html/[html]link://タグ/regex/[正規表現]