准备资料

jsoup 是一款 Java 的HTML 解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于JQuery的操作方法来取出和操作数据。

jsoup的主要功能如下:

  1. 从一个URL,文件或字符串中解析HTML;
  2. 使用DOM或CSS选择器来查找、取出数据;
  3. 可操作HTML元素、属性、文本;

如果对jsoup不熟悉,请移步http://jsoup.org/

 

 

JDIC 全程是 JDesktop Integration Components 目的是构建消除本机应用程序和 Java 等价物之间差距的组件。JDIC 单一的 Java API 允许应用程序接进本机操作系统特性,同时保持跨平台支持。它目前提供了本机 Web 浏览器(Internet Explorer 或 Mozilla) 支持、系统托盘支持、文件扩展集成和其他桌面特性。

官网:http://java.net/projects/jdic/

svn地址,直接下了看例子吧:https://svn.java.net/svn/jdic~svn

helloword程序:http://plplum.blog.163.com/blog/static/31032400200910994034328/

 

 

 

另,刚刚找到的一篇好文章,Java 网页浏览器组件介绍:http://www.ibm.com/developerworks/cn/java/j-lo-browser/index.html

 

 

动态核心

jsoup 的解析很好用,但是jsoup不能解析动态的代码,于是就有了JDIC调用ie内核,然后执行

Java代码 

 

java 解析html 带js的标签 java获取html_html

1. String jscript =   "function getAllHtml() {"+  
2.         "var a='';" +  
3.         "a = '<html><head><title>';" +  
4.         "a += document.title;"+       
5.         "a += '</title></head>';"+  
6.          "a += document.body.outerHTML;"+  
7.         "a += '</html>';"+  
8.         "return a;"+  
9.     "}"+  
10.     "getAllHtml();";  
11.   String result = webBrowser.executeScript(jscript);

 这段代码得到当前的html,然后交由jsoup 进行解析

Java代码 

 

java 解析html 带js的标签 java获取html_html

1. Document doc=Jsoup.parse(result);

  

例子

示例目标:

招聘网站,希望出来的结果按照公司规模来排序

购物网站,希望商品按照评论的多少来排序

图片搜索,快速保存所有的结果

。。。。。。

 

下面的演示实现了找出标题,百度图片搜索的前2页,智联招聘的前6页

 

 

Java代码 

 

java 解析html 带js的标签 java获取html_html

1. package ins1000.main;  
2.   
3. import ins1000.dialect.DefiniteUrl;  
4. import ins1000.dialect.impl.CopyOfDefiniteUrl_zhilianzhaoping;  
5. import ins1000.dialect.impl.DefiniteUrl_baiduMap;  
6. import ins1000.util.BrowserReadHtml;  
7.   
8. import java.util.ArrayList;  
9. import java.util.List;  
10.   
11. /** 
12.  * 以网页翻页为例子 
13.  * @author Administrator 
14.  * 
15.  */  
16. public class Main{  
17.     static List<DefiniteUrl> definiteUrls=new ArrayList<DefiniteUrl>();  
18.     static{  
19.         definiteUrls.add(new DefiniteUrl_baiduMap());  
20.         definiteUrls.add(new CopyOfDefiniteUrl_zhilianzhaoping());  
21.     }  
22.       
23.     public static void main(String[] args) throws Exception {  
24.         for(DefiniteUrl du:definiteUrls){  
25.             BrowserReadHtml brh= new BrowserReadHtml(du);  
26.             brh.begin();  
27.         }  
28.     }  
29.       
30.     public static void finish(DefiniteUrl du) {  
31.         definiteUrls.remove(du);  
32.         if(definiteUrls.size()==0){  
33.             System.exit(0);  
34.         }  
35.           
36.     }  
37.   
38. }

 主类,扩展的时候直接添加definiteUrls.add(new xxx());即可

 

 

Java代码 

 

java 解析html 带js的标签 java获取html_html

1. package ins1000.util;  
2. import ins1000.dialect.DefiniteUrl;  
3. import java.awt.BorderLayout;  
4. import java.net.URL;  
5. import java.util.Timer;  
6. import java.util.TimerTask;  
7.   
8. import javax.swing.JFrame;  
9. import javax.swing.JPanel;  
10.   
11. import org.jdesktop.jdic.browser.WebBrowser;  
12. import org.jdesktop.jdic.browser.WebBrowserEvent;  
13. import org.jdesktop.jdic.browser.WebBrowserListener;  
14. import org.jsoup.Jsoup;  
15. import org.jsoup.nodes.Document;  
16.   
17.   
18. /** 
19.  * 动态读取页面的html 
20.  * @author ckf 
21.  * 
22.  */  
23. public class BrowserReadHtml {  
24.     private DefiniteUrl definiteUrl;  
25.       
26.     public BrowserReadHtml(DefiniteUrl definiteUrl) {  
27.         this.definiteUrl=definiteUrl;  
28.     }  
29.       
30.     private  JFrame frame;  
31.     private JPanel panel_name=new JPanel();  
32.     private WebBrowser webBrowser = new WebBrowser();  
33.     public void begin() throws Exception{  
34.         initwebBrowser();   
35.         frame = new JFrame("Browser Test");  
36.         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
37.         frame.getContentPane().add(webBrowser);  
38.         frame.pack();  
39.         frame.setSize(900,500);  
40.         frame.setLocation((int)(100*Math.random()), (int)(100*Math.random()));  
41.         frame.setVisible(definiteUrl.isVisible());  
42.     }  
43.     int begincount;  
44.     private void initwebBrowser()  throws Exception{  
45.   
46.         panel_name.add(webBrowser, BorderLayout.CENTER);  
47.         webBrowser .setURL(new URL(definiteUrl.getUrl()));  
48.         webBrowser .addWebBrowserListener(new WebBrowserListener() {  
49.       public void documentCompleted(WebBrowserEvent event) {  
50.           if(begincount==0){  
51.               getThisPageResult();  
52.           }  
53.           begincount++;  
54.       }  
55.     public void downloadStarted(WebBrowserEvent event) {}  
56.       public void downloadCompleted(WebBrowserEvent event) {      }  
57.       public void downloadProgress(WebBrowserEvent event) {       }  
58.       public void downloadError(WebBrowserEvent event) {          }  
59.       public void titleChange(WebBrowserEvent event) {        }    
60.       public void statusTextChange(WebBrowserEvent event) {       }  
61.      public void windowClose(WebBrowserEvent arg0) {     }  
62.   
63.      });  
64.           
65.     }  
66.       
67.     private void callback(String result) {  
68.         Document doc=Jsoup.parse(result);  
69.         definiteUrl.page(doc);  
70.         if(definiteUrl.isEndPage(doc)){  
71.             frame.dispose();  
72.             definiteUrl.finish();  
73.         }else{  
74.             webBrowser.executeScript(definiteUrl.getNextPageJavaScript(doc));  
75.             getThisPageResult();  
76.         }  
77.     }  
78.     private void getThisPageResult() {  
79.         Timer timer = new Timer(false);  
80.         timer.schedule(new AllTask(), 1 * 1000);  
81.     }  
82.       
83.   
84.      class AllTask extends TimerTask {  
85.         public void run() {  
86.             String jscript =   "function getAllHtml() {"+  
87.             "var a='';" +  
88.             "a = '<html><head><title>';" +  
89.             "a += document.title;"+       
90.             "a += '</title></head>';"+  
91.              "a += document.body.outerHTML;"+  
92.             "a += '</html>';"+  
93.             "return a;"+  
94.         "}"+  
95.         "getAllHtml();";  
96.       String result = webBrowser.executeScript(jscript);  
97.       callback(result);  
98.         }  
99.     }  
100. }

这个类是调用ie浏览器,执行javascript代码,可以不管

 

 

 

Java代码 

 

java 解析html 带js的标签 java获取html_html

1. package ins1000.dialect;  
2.   
3.   
4. import ins1000.main.Main;  
5.   
6. import org.jsoup.nodes.Document;  
7.   
8. /** 
9.  * 抽象类,每个具体的网站都要继承此类 
10.  * @author Administrator 
11.  * 
12.  */  
13. public abstract class DefiniteUrl{  
14.     private String url;  
15.     private boolean visible;  
16.     public DefiniteUrl(String url){  
17.         this.url=url;  
18.         visible=true;  
19.     }  
20.       
21.     public abstract String getNextPageJavaScript(Document doc);  
22.       
23.     public abstract boolean isEndPage(Document doc);  
24.       
25.     public abstract void page(Document doc);  
26.   
27.       
28.     public String getUrl() {  
29.         return url;  
30.     }  
31.   
32.     public void setUrl(String url) {  
33.         this.url = url;  
34.     }  
35.   
36.     public boolean isVisible() {  
37.         return visible;  
38.     }  
39.   
40.     public void setVisible(boolean visible) {  
41.         this.visible = visible;  
42.     }  
43.   
44.     public void finish() {  
45.         Main.finish(this);  
46.     }  
47.   
48.   
49.       
50. }

 

 这个是抽象类,每个网站要实现对应的方法

getNextPageJavaScript下一页javascript代码,可以是点击下一页按钮,也可以是直接换url

isEndPage是否为最后一页

page当前页面最终的html代码(动态的html代码)

 

 

 

//以下为具体的实现类,扩展的时候直接继承一个DefiniteUrl

 

Java代码 

 

java 解析html 带js的标签 java获取html_html

1. package ins1000.dialect.impl;  
2.   
3. import org.jsoup.nodes.Document;  
4. import org.jsoup.nodes.Element;  
5. import org.jsoup.select.Elements;  
6. import ins1000.dialect.DefiniteUrl;  
7.   
8. public class DefiniteUrl_baiduMap  extends DefiniteUrl{  
9.   
10.     public DefiniteUrl_baiduMap() {  
11.         //设置网站入口地址  
12.         super("http://image.baidu.com/i?ct=201326592&cl=2&lm=-1&tn=baiduimage&istype=2&fm=index&pv=&z=0&word=%C2%E3%BB%E9%CA%B1%B4%FA&s=0");  
13.         //设置窗口是否可视化,默认为true  
14.         //setVisible(false);  
15.     }  
16.     private int count=1;  
17.     @Override  
18.     public String getNextPageJavaScript(Document doc) {  
19.         count++;  
20.         Element el= doc.select("#pgw").select("a").last();  
21.         return el.attr("onclick");  
22.     }  
23.   
24.     @Override  
25.     public boolean isEndPage(Document doc) {  
26.         if(count>=2){  
27.             return true;  
28.         }else{  
29.             return false;  
30.         }  
31.     }  
32.   
33.     @Override  
34.     public void page(Document doc) {  
35.         Elements els= doc.select("#imgid").select("dl");  
36.         for(Element el:els){  
37.             Element img=el.select("img").first();  
38.             Element link=el.select("dt").select("a").first();  
39.             System.out.println(link.text()+"=======>"+img.absUrl("src"));  
40.         }  
41.     }  
42.   
43. }

 

 

 

Java代码 

 

java 解析html 带js的标签 java获取html_html

    1. package ins1000.dialect.impl;  
    2.   
    3. import org.jsoup.nodes.Document;  
    4. import org.jsoup.nodes.Element;  
    5. import org.jsoup.select.Elements;  
    6.   
    7. import ins1000.dialect.DefiniteUrl;  
    8.   
    9. public class CopyOfDefiniteUrl_zhilianzhaoping  extends DefiniteUrl{  
    10.   
    11.     public CopyOfDefiniteUrl_zhilianzhaoping() {  
    12.         //设置网站入口地址  
    13.         super("http://sou.zhaopin.com/jobs/jobsearch_jobtype.aspx?in=210500&jl=%E6%B7%B1%E5%9C%B3&kw=java&sm=1&p=1");  
    14.         //设置窗口是否可视化,默认为true  
    15.         //setVisible(false);  
    16.     }  
    17.     private int count=1;  
    18.     @Override  
    19.     public String getNextPageJavaScript(Document doc) {  
    20.           
    21.           
    22.         String url="http://sou.zhaopin.com/jobs/jobsearch_jobtype.aspx?in=210500&jl=%E6%B7%B1%E5%9C%B3&kw=java&sm=1&p="+count;  
    23.         String next="window.location.href='"+url+"';";  
    24.           
    25.         count++;  
    26.         return next;  
    27.     }  
    28.       
    29.     @Override  
    30.     public boolean isEndPage(Document doc) {  
    31.         if(count>=6){  
    32.             return true;  
    33.         }else{  
    34.             return false;  
    35.         }  
    36.     }  
    37.   
    38.     @Override  
    39.     public void page(Document doc) {  
    40.         Elements els= doc.select("#joblist").select("[class=trW2]");  
    41.         for(Element el:els){  
    42.             try {  
    43.                 System.out.print(el.select("a").first().text());  
    44.                 System.out.print("==========>");  
    45.                 System.out.println(el.select("a").eq(1).text());  
    46.             } catch (Exception e) {  
    47.             }  
    48.         }  
    49.       
    50.     }  
    51.   
    52. }

    有图有真相


     

    附件中有源码,eclipse导出

     

     

     

     

    遗留问题

     

     

    Java代码 

     

    java 解析html 带js的标签 java获取html_html

    1. private void getThisPageResult() {  
    2.     Timer timer = new Timer(false);  
    3.     timer.schedule(new AllTask(), 1 * 1000);  
    4. }  
    5.   
    6.   
    7.  class AllTask extends TimerTask {  
    8.     public void run() {  
    9.         String jscript =   "function getAllHtml() {"+  
    10.         "var a='';" +  
    11.         "a = '<html><head><title>';" +  
    12.         "a += document.title;"+       
    13.         "a += '</title></head>';"+  
    14.          "a += document.body.outerHTML;"+  
    15.         "a += '</html>';"+  
    16.         "return a;"+  
    17.     "}"+  
    18.     "getAllHtml();";  
    19.   String result = webBrowser.executeScript(jscript);  
    20.   callback(result);  
    21.     }

    上面是当前代码,求更好的解决方案

     

    现在取得当前的html使用了定时器,1秒后执行,感觉很不精确,有没有什么更好的方式,比如判断当前页面所有的内容都已经加载完了,其它的javascript都已经执行完了的代码?

    • DynamicParseHtml.rar (1.1 MB)
    • 下载次数: 1334
    • 查看图片附件