做文字的网站,自学搭建网站,电子菜单制作app,上海网站jianshe一、 目标 获取网页中的超链接及链接名#xff0c;如从http://www.hao123.com/开始#xff0c;抓取所有hao123链接到的超链接#xff0c;再以获取到的链接网页为目标#xff0c;获取它所链接到的网页。 二、环境及开发工具 环境#xff1a;Java 工具#xff1a;MyEclip…一、 目标 获取网页中的超链接及链接名如从http://www.hao123.com/开始抓取所有hao123链接到的超链接再以获取到的链接网页为目标获取它所链接到的网页。 二、环境及开发工具 环境Java 工具MyEclipse 开发包如图 三、 原理 网络爬虫是一个自动提取网页的程序它为搜索引擎从万维网上下载网页是搜索引擎的重要组成。爬虫从一个或若干初始网页的URL开始获得初始网页上的URL在抓取网页的过程中不断从当前页面上抽取新的URL放入队列直到满足系统的一定停止条件。 而htmlparser能够很容易地提取到网页的信息例如对HTML进行有效信息搜索、链接提取、用于自动给页面的链接文本加上链接的标签 、资源提取例如对一些图片、声音的资源的处理将网页内容保存到本地等等极大地方便开发。 四、类分析如下图 各类说明 FileNameList内部用linkedlist存放解析出来的xml文件名即每一个链接的text IndexsList: 用链接来记录索引,即是每一层的层数 LinksList: 记录解析过程中的超链接, Parse:主要解析功能类 ParseTool主要负责获得并初始化解析的参数 ResultBean封装要解析的数据方便写入xml文件中 UserCase提供一个用例样例 WritetoXML:把每一层的解析结果写入xml文件中 五、类实现如下 1.FileNameList 1 /**2 * 3 */4 package cn.guet.deep;5 6 import java.net.URL;7 import java.util.LinkedList;8 9 /**
10 * author 梁渝铭
11 * project name:HTMLParser
12 * date:2011-11-24
13 */
14 public class FileNameList {
15
16 /*
17 * 用链接来记录xml文件名
18 */
19 private static LinkedListString links new LinkedListString();
20 private static FileNameList fileNameList new FileNameList();
21 private static int index 0;
22 // 控制空链接名时用来生成xml文件名
23 private static int flag 0;
24
25 private FileNameList() {
26
27 }
28
29 public static FileNameList getInstance() {
30 return fileNameList;
31 }
32
33 /*
34 * 入队列操作,检查链接名是否为空
35 */
36 public void enQueue(String name) {
37 // 检查文件名不合法时处理
38 if(links.contains(name)){
39 links.add(name flag);
40 return;
41 }
42 if (name ! null) {
43 links.addLast(name);
44 }else {
45 links.addLast((index flag));
46 }
47 }
48
49 public String next() {
50 return links.get(index);
51 }
52
53 public void free() {
54 links.clear();
55 }
56
57 } 2.IndexsList 1 /**2 * 3 */4 package cn.guet.deep;5 6 import java.util.LinkedList;7 8 /**9 * author 梁渝铭
10 * project name:HTMLParser
11 * date:2011-11-21
12 * 记录每一层的每一个file的索引
13 */
14 public class IndexsList {
15
16 /*用链接来记录索引
17 */
18 private static LinkedListInteger indexList new LinkedListInteger();
19 private static IndexsList indexInstance new IndexsList();
20 //控制队列出队
21 private static int flag 0;
22
23 private IndexsList(){
24
25 }
26
27 public static IndexsList getInstance(){
28 return indexInstance;
29 }
30
31 public int next(){
32 return indexList.get(flag);
33 }
34
35 /*入队列操作
36 */
37 public void enQueue(int index){
38 indexList.addLast(index);
39 }
40
41 public int get(int index){
42 return indexList.get(index);
43 }
44
45 public void free(){
46 indexList.clear();
47 }
48 } 3.LinksList 1 /**2 * 3 */4 package cn.guet.deep;5 6 import java.util.HashSet;7 import java.util.LinkedList;8 import java.util.Set;9
10 /**
11 * author 梁渝铭
12 * project name:HTMLParser
13 * date:2011-11-21 记录解析过程中的超链接
14 */
15 public class LinksList {
16
17 /*
18 * 用链接来记录队列
19 */
20 private static LinkedListString links new LinkedListString();
21 private static LinksList linksInstance new LinksList();
22 //记录已经访问了的url防止重复访问
23 private static SetString visitedSet new HashSetString();
24 //单例
25 private LinksList() {
26
27 }
28
29 public static LinksList getInstance() {
30 return linksInstance;
31 }
32
33 /*
34 * 入队列操作
35 */
36 public void enQueue(String url) {
37 // 先入队确保每个url只被访问一次,去掉链接最后的/
38 /* String url_temp url;
39 if (url.endsWith(/)) {
40 url_temp url.substring(0, url.lastIndexOf(/));
41 }
42 visitedSet.add(url_temp);
43 if (links.isEmpty() || !visitedSet.contains(url_temp))*/
44 if(!visitedSet.contains(url))
45 links.addLast(url);
46 }
47
48 public String get(int index) {
49 return links.get(index);
50 }
51
52 public String next() {
53 String link links.getFirst();
54 links.removeFirst();
55 return link;
56 }
57
58 public void free(){
59 links.clear();
60 }
61
62 } 4.Parse 1 /**2 * 3 */4 package cn.guet.deep;5 6 import java.io.IOException;7 import java.util.LinkedList;8 9 import org.apache.log4j.Logger;10 import org.htmlparser.NodeFilter;11 import org.htmlparser.Parser;12 import org.htmlparser.filters.NodeClassFilter;13 import org.htmlparser.tags.LinkTag;14 import org.htmlparser.util.NodeList;15 import org.htmlparser.util.ParserException;16 17 18 /**19 * author 梁渝铭20 * project name:HTMLParser21 * date:2011-11-21 主要解析类22 */23 public class Parse {24 private Logger logger Logger.getLogger(this.getClass());25 /*26 * 初始化参数27 */28 private static LinksList linksList LinksList.getInstance();29 private static IndexsList indexsList IndexsList.getInstance();30 private static WritetoXML writetoXML new WritetoXML();31 private static FileNameList fileNameList FileNameList.getInstance();32 private static int floor 0;33 private static int floor_count 0;34 //每一个超链接解析出来的超链接的总数35 private static int len 0;36 //xml使用的文件名37 38 private static String path null;39 private static int count 0;40 public Parse(){41 indexsList.enQueue(1);42 }43 44 public int getFloor() {45 return floor;46 }47 48 public void setFloor(int floor) {49 Parse.floor floor;50 }51 52 public void setUrl(String url) {53 fileNameList.enQueue(index);54 linksList.enQueue(url);55 }56 57 public void setPath(String path) {58 Parse.path path;59 }60 61 //释放资源62 public void free(){63 try {64 linksList.free();65 logger.info(linksList had released...);66 indexsList.free();67 logger.info(linksList had released...);68 fileNameList.free();69 logger.info(linksList had released...);70 logger.info(all had released...);71 } catch (Exception e) {72 logger.error(e.getMessage());73 }74 }75 76 // 补全url的地址77 public String fillUrl(String domain,String url) {78 return url.indexOf(http://) ! -1 ? url : domain url;79 }80 //替换文件名不支持的字符81 public String replaceSpe(String link_name){82 link_name link_name.replaceAll([?], )83 .replaceAll([nbsp;], )84 .replaceAll([amp;], )85 .replaceAll([lt;], )86 .replaceAll([gt;], )87 .replaceAll([ ], -);88 return link_name;89 }90 /*91 * 解析类采用NodeFilter过滤92 */93 public void extractLinks() throws IOException {94 try {95 while(floor ! 0) {96 int temp indexsList.next();97 floor_count;98 //统计每一层的文件数99 int file_count 0;
100 for (int i 0; i temp; i) {
101 logger.info(该层的文件总数temp);
102 //外层循环控制每一次有的文件数
103 file_count;
104 //每层中的每一个xml文件对应的结果集
105 LinkedListResultBean resultList new LinkedListResultBean();;
106 NodeFilter filter new NodeClassFilter(LinkTag.class);
107 Parser parse new Parser();
108 String url linksList.next();
109 try {
110 //使解析跳过异常如500403404。。。造成解析异常而中止的链接
111 //让parser继续解析
112 logger.info(try parse.....);
113 parse.setURL(url);
114 parse.setEncoding(parse.getEncoding());
115 logger.info(set Encoding....);
116 } catch (Exception e) {
117 logger.error(e.getMessage());
118 e.printStackTrace();
119 file_count--;
120 continue;
121 }
122 //内层循环控制每一层中的由上一层链接解析出来的链接
123 logger.info(before extract list....parse.getURL());
124 NodeList list;
125 try{
126 list parse.extractAllNodesThatMatch(filter);
127 }catch(ParserException e){
128 e.printStackTrace();
129 continue;
130 }
131 logger.info(extracting ....);
132 for(len0;lenlist.size();len){
133 LinkTag node (LinkTag) list.elementAt(len);
134 String link_name replaceSpe(node.getLinkText());
135 String link fillUrl(url,node.extractLink());
136 //封装结果并写入xml文件中
137 ResultBean resultBean new ResultBean();
138 resultBean.setName(link_name);
139 resultBean.setLink(link);
140 resultList.add(resultBean);
141 fileNameList.enQueue(link_name);
142 linksList.enQueue(link);
143 logger.info(第(count)个链接, 第 floor_count层:第file_count个文件name: node.getLinkText()link to: link);
144 }
145 indexsList.enQueue(len1);
146 try{
147 writetoXML.writeToXML(path, floor_count,fileNameList.next(), resultList);
148 }catch(Exception e){
149 e.printStackTrace();
150 continue;
151 }
152
153 }
154 floor--;
155 }
156 } catch (Exception e) {
157 logger.error(e.getMessage());
158 e.printStackTrace();
159 }
160 }
161 } 5.ParseTool 1 /**2 * 3 */4 package cn.guet.deep;5 6 import java.io.IOException;7 8 import org.htmlparser.Parser;9
10 /**
11 * author 梁渝铭
12 * project name:HTMLParser
13 * date:2011-11-21
14 * 解析工具类
15 */
16 public class ParseTool {
17
18 private Parse parse new Parse();
19
20 //开始解析
21 public void parse() throws IOException{
22 parse.extractLinks();
23 }
24
25 //设置解析的url
26 public void setUrl(String url){
27 parse.setUrl(url);
28 }
29
30 //设置解析存放路径
31 public void setPath(String path){
32 parse.setPath(path);
33 }
34
35 //设置要解析的层数
36 public void setFloor(int floor){
37 parse.setFloor(floor);
38 }
39
40 //释放资源
41 public void free(){
42 parse.free();
43 }
44
45 } 6.WritetoXML 1 /**2 * 3 */4 package cn.guet.deep;5 6 import java.io.File;7 import java.io.FileOutputStream;8 import java.io.IOException;9 import java.util.LinkedList;10 11 import org.apache.log4j.Logger;12 import org.dom4j.Document;13 import org.dom4j.DocumentHelper;14 import org.dom4j.Element;15 import org.dom4j.io.OutputFormat;16 import org.dom4j.io.XMLWriter;17 18 /**19 * author 梁渝铭20 * project name:HTMLParser21 * date:2011-11-23 22 * 把解析得到的链接按层写入xml文件中23 */24 public class WritetoXML {25 private Logger logger Logger.getLogger(this.getClass());26 27 /*28 * 存放的xml样式 29 * links 30 * link_sumary31 * link_number每个xml中总共的链接数/link_number32 * /link_sumary33 * link 34 * name links_name /name 35 * address link_address address36 * /link 37 * ... 38 * /links39 */40 private static int index 0;41 /*42 * path表示xml文件存放的路径floor表示文件的层次,link_name作为xml文件名43 */44 public void writeToXML(String path, int floor, String link_name,45 LinkedListResultBean links) throws IOException {46 //创建一个新的xml文档47 Document document DocumentHelper.createDocument();48 Element root document.addElement(links);49 Element link_summary root.addElement(link_summary);50 Element link_number link_summary.addElement(link_number);51 link_number.addText(String.valueOf(links.size()));52 /*53 * 通过循环将解析结果集中的对象数据转换成xml节点54 */55 for (int i 0; i links.size(); i) {56 Element link root.addElement(link);57 Element name link.addElement(name);58 Element address link.addElement(address);59 name.addText(links.get(i).getName());60 address.addText(links.get(i).getLink());61 }62 path handlePath(path, floor, link_name);63 documentToXML(document, path);64 }65 66 /*67 * 把链接写入xml中68 */69 70 public void documentToXML(Document document, String filePath) {71 72 // 使用org.dom4j.io包下的xmlwriter类将dom4j的文档树对象转换为xml输出73 XMLWriter xmlWriter null;74 try {75 // 创建有格式和缩进的格式化输出对象76 OutputFormat format OutputFormat.createPrettyPrint();77 format.setEncoding(UTF-8);78 // 将新的文件输出流对象和格式化对象封装进实例化的xmlwriter对象中79 xmlWriter new XMLWriter(new FileOutputStream(filePath), format);80 xmlWriter.write(document);81 } catch (IOException e) {82 logger.error(e.getMessage());83 }finally{84 //防止意外而无法关闭资源造成浪费85 try {86 xmlWriter.close();87 } catch (IOException e) {88 e.printStackTrace();89 }90 }91 }92 93 /*94 * 按层分文件夹处理每层的文件名路径等返回一个xml文件的路径名95 * 如96 * D/test/floor_1/index.xml97 */98 public String handlePath(String path, int floor, String link_name)99 throws IOException {
100 String filePath path;
101 File file new File(filePath);
102 //检查路径是否存在
103 if (!file.exists()) {
104 file.mkdirs();
105 }
106 filePath path // floor_ floor;
107 if(!(file new File(filePath)).exists()){
108 file.mkdirs();
109 }
110 file null;
111 if(link_name.equals())
112 link_name link_name index;
113 return filePath // link_name .xml;
114 }
115 } 六、输出结果 1.目录集合一个文件夹floor_x表示某一爬行层次 2.一个文件夹存放着某一层爬行过的网页一个文件记录表示一个网页 3.一个XML文件记录一个网页上的目标链接记录多个目标链接地址 转载于:https://www.cnblogs.com/sl-shilong/archive/2013/02/03/2890824.html