准备资料
jsoup 是一款 Java 的HTML 解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于JQuery的操作方法来取出和操作数据。
jsoup的主要功能如下:
- 从一个URL,文件或字符串中解析HTML;
- 使用DOM或CSS选择器来查找、取出数据;
- 可操作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代码
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代码
1. Document doc=Jsoup.parse(result);
例子
示例目标:
招聘网站,希望出来的结果按照公司规模来排序
购物网站,希望商品按照评论的多少来排序
图片搜索,快速保存所有的结果
。。。。。。
下面的演示实现了找出标题,百度图片搜索的前2页,智联招聘的前6页
Java代码
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代码
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代码
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代码
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代码
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代码
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
- 查看图片附件