يمكننا عن طريق الجافا الوصول إلى كل الوسوم الموجودة في صفحة html، والتعرف على ميزات كل وسم ومحتواه.
في هذا المثال سنتعرف على كيفية استخراج الروابط الموجودة في الوسم <a>، هذا الوسم يتوفر على ميزة href هي التي تحتوي على الرابط.
سنستعمل الفئتين ParserDelegator و ParserCallback.
عندما ننشئ object من فئة ParserDelegator، فإننا نمرر له Reader الذي يقوم بقراءة الملف html، ونمرر له أيضا object من فئة ParserCallback.
الParserDelegator الذي أنشانا يقوم بعمل parsing للملف html وذلك بالنداء على parser خاص بالhtml، هذا الparser يقوم في كل مرة يجد فيها وسما بالنداء على طريقة معينة موجودة في ParserCallback، مثلا عندما يدخل الparser لوسم ما، فإنه ينادي على الطريقة
handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos)
وعندما يخرج منه فإنه ينادي على الطريقة
handleEndTag(HTML.Tag t, int pos)
كلتا الطريقتين موجودتان في الفئة ParserCallback.
الآن ما نريد فعله هو استخراج كل الروابط الموجودة في صفحة html وإضافتها إلى ArrayList، لهذا الغرض سنكتب فئة ترث من ParserCallback ونعمل override للطريقة handleStartTag. هذه الأخيرة تنتظر ثلاث arguments، الأول من فئة Tag، وهو يمثل الوسم الذي نحن بصدد الدخول إليه، الargument الثاني هو من فئة MutableAttributeSet، هذه الفئة تعمل تقريبا مثل dictionary، أي أنها عبارة عن أزواج key/value، هذا الargument يحتوي على المزايا ( attributes ) الخاصة بالوسم، الargument الأخير لن نحتاجه.
class LinkAction extends HTMLEditorKit.ParserCallback {
@Override
public void handleStartTag(Tag t, MutableAttributeSet a, int pos) {
if (t == Tag.A) {
String href = (String)a.getAttribute(Attribute.HREF);
if (href != null) {
links.add(href);
}
}
}
}كما سبق وقلنا فإن handleStartTag هي التي ينادي عليها الparser عند الدخول لوسم ما، لذلك فإننا نقوم بoverride ونكتبها لتلبي غرضنا. أولا نتحقق من أن الوسم الحالي هو وسم <a>، إذا كان كذلك فإننا نستخرج الميزة href ونضيفها إلى الArrayList الذي يحتوي على الروابط، أي المتغير links كما في المثال
سنقوم الآن بكتابة البرنامج
public class ExtractLinks {
private ArrayList<String> links;
private BufferedReader reader;
private ParserDelegator delegator;
......أعلنا ثلاث متغيرات، المتغير الاول من فئة ArrayList هو الذي سيحتوي على الروابط، المتغير الثاني من فئة BufferedReader هو الذي سيقوم بقراءة الملف html، المتغير الثالث من فئة ParserDelegator هو الذي سيقوم بعملية الparsing
public ExtractLinks(URL url) throws IOException {
links = new ArrayList<String>();
reader = new BufferedReader(new InputStreamReader(url.openStream()));
delegator = new ParserDelegator();
}هذا الconstructor ينتظر argument من فئة URL، وهو يمثل عنوان الصفحة html التي سنعمل عليها. داخل الconstructor نقوم بعمل instanciation للمتغيرات، بالنسبة للمتغير من فئة BufferedReader فقد مررنا له InputStreamReader، حيث أن url.openStream() تعيد binary stream بينما BufferedReader عبارة عن character stream، لذلك نستعمل InputStreamReader الذي يحول من binary stream إلى character stream
public ArrayList<String> extractLinks() throws IOException {
delegator.parse(reader, new LinkAction(), true);
return links;
}داخل الطريقة extractLinks ننادي على الطريقة parse الخاصة بParserDelegator ونمرر لها الBufferedReader الذي أنشأنا، ثم الفئة التي ترث من ParserCallback والتي كتبناها فوق، وboolean يحدد هل يجب الأخد بعين الإعتبار الcharset أو لا
المثال بالكامل
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.html.HTML.Attribute;
import javax.swing.text.html.HTML.Tag;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.parser.ParserDelegator;
public class ExtractLinks {
private ArrayList<String> links;
private BufferedReader reader;
private ParserDelegator delegator;
public ExtractLinks(URL url) throws IOException {
links = new ArrayList<String>();
reader = new BufferedReader(new InputStreamReader(url.openStream()));
delegator = new ParserDelegator();
}
public ArrayList<String> extractLinks() throws IOException {
delegator.parse(reader, new LinkAction(), true);
return links;
}
class LinkAction extends HTMLEditorKit.ParserCallback {
@Override
public void handleStartTag(Tag t, MutableAttributeSet a, int pos) {
if (t == Tag.A) {
String href = (String)a.getAttribute(Attribute.HREF);
if (href != null) {
links.add(href);
}
}
}
}
public static void main(String[] args) {
try {
ExtractLinks extract = new ExtractLinks(new URL("http://www.google.com"));
ArrayList<String> links = extract.extractLinks();
for (String s : links) {
System.out.println(s);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
