java实现爬虫给app提供数据jsoup网络爬虫.docx
- 文档编号:26958539
- 上传时间:2023-06-24
- 格式:DOCX
- 页数:11
- 大小:19.18KB
java实现爬虫给app提供数据jsoup网络爬虫.docx
《java实现爬虫给app提供数据jsoup网络爬虫.docx》由会员分享,可在线阅读,更多相关《java实现爬虫给app提供数据jsoup网络爬虫.docx(11页珍藏版)》请在冰豆网上搜索。
java实现爬虫给app提供数据jsoup网络爬虫
java实现爬虫给app提供数据(jsoup网络爬虫)
需求##
最近基于MaterialDesign重构了自己的新闻App,数据来源是个问题。
有前人分析了知乎日报、凤凰新闻等API,根据相应的URL可以获取新闻的JSON数据。
为了锻炼写代码能力,笔者打算爬虫新闻页面,自己获取数据构建API。
本文链接转载请注明出处
效果图
下图是原网站的页面
爬虫获取了数据,展示到APP手机端
爬虫思路
CreatedwithRapha?
l2.1.0开始基于Get请求获取URL对于的网页Html利用Jsoup把Html解析为Document利用Dom的getElementsById等方法获取标题、发布时间、内容等根据标题、发布时间、内容构建javabean给APP使用结束
关于App的实现过程可以参看这几篇文章,本文主要讲解一下如何爬虫数据。
Android下如何录制App操作生成Gif动态图
AndroidMaterialDesign学习之RecyclerView代替ListView
仿网易新闻的页面(ViewPager作为RecyclerView的Header)
Jsoup简介
Jsoup是一个Java的开源HTML解析器,可直接解析某个URL地址、HTML文本内容。
Jsoup主要有以下功能:
-从一个URL,文件或字符串中解析HTML;
-使用DOM或CSS选择器来查找、取出数据;
-对HTML元素、属性、文本进行操作;
-清除不受信任的HTML(来防止XSS攻击)
到官网下载相应的Jsoup依赖包http:
//jsoup.org/download
爬虫过程
Get请求获取网页HTML
新闻网页Html的DOM树如下所示:
下面这段代码根据指定的url,用代码获取get请求返回的html源代码。
publicstaticStringdoGet(StringurlStr)throwsCommonException{
URLurl;
Stringhtml="";
try{
url=newURL(urlStr);
HttpURLConnectionconnection=(HttpURLConnection)url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(5000);
connection.setDoInput(true);
connection.setDoOutput(true);
if(connection.getResponseCode()==200){
InputStreamin=connection.getInputStream();
html=StreamTool.inToStringByByte(in);
}else{
thrownewCommonException("新闻服务器返回值不为200");
}
}catch(Exceptione){
e.printStackTrace();
thrownewCommonException("get请求失败");
}
returnhtml;
}
1234567891011121314151617181920212223
InputStreamin=connection.getInputStream();将得到输入流转化为字符串是个普遍需求,我们将其抽象出来,写一个工具方法。
publicclassStreamTool{
publicstaticStringinToStringByByte(InputStreamin)throwsException{
ByteArrayOutputStreamoutStr=newByteArrayOutputStream();
byte[]buffer=newbyte[1024];
intlen=0;
StringBuildercontent=newStringBuilder();
while((len=in.read(buffer))!
=-1){
content.append(newString(buffer,0,len,"UTF-8"));
}
outStr.close();
returncontent.toString();
}
}
1234567891011121314
解析HTML获取标题
利用google浏览器的审查元素,找出新闻标题对于的html代码:
关于举办《经典音乐作品欣赏与人文审美》讲座的通知
1234567
我们需要从上面的HTML中找出id="article_title"的部分,使用getElementById(Stringid)方法
StringhtmlStr=HttpTool.doGet(urlStr);
//将获取的网页HTML源代码转化为Document
Documentdoc=Jsoup.parse(htmlStr);
ElementarticleEle=doc.getElementById("article");
//标题
ElementtitleEle=articleEle.getElementById("article_title");
StringtitleStr=titleEle.text();123456789
获取发布日期、信息来源
同样找出对于的HTML代码
2015-05-28
来源:
浏览次数:
477
1234567891011
思路也和上面类似,使用getElementById(Stringid)方法找出id="article_detail"为Element,再利用getElementsByTag获取span部分。
因为一共有3个...,所以返回的是Elements而不是Element。
//article_detail包括了2016-01-15来源:
浏览次数:
177
ElementdetailEle=articleEle.getElementById("article_detail");
Elementsdetails=detailEle.getElementsByTag("span");
//发布时间
StringdateStr=details.get(0).text();
//新闻来源
StringsourceStr=details.get
(1).text();
12345678910
解析浏览次数
如果打印出上面的details.get
(2).text(),只会得到
浏览次数:
1
没有浏览次数?
为什么呢?
因为浏览次数是JavaScript渲染出来的,Jsoup爬虫可能仅仅提取HTML内容,得不到动态渲染出的数据。
解决方法有两种
在爬虫的时候,内置一个浏览器内核,执行js渲染页面后,再抓取。
这方面对应的工具有Selenium、HtmlUnit或者PhantomJs。
可以查看这篇文章《抓取前端渲染的页面》http:
//webmagic.io/docs/zh/posts/chx-cases/js-render-page.html。
所以分析JS请求,找到对应数据的请求url
如果你访问上面的url
document.write(478)1
这个478就是我们需要的浏览次数,我们对上面的url做get请求,得到返回的字符串,利用正则找出其中的数字。
//访问这个新闻页面,浏览次数会+1,次数是JS渲染的
StringjsStr=HttpTool.doGet(COUNT_BASE_URL+currentPage);
intreadTimes=Integer.parseInt(jsStr.replaceAll("\\D+",""));
//或者使用下面这个正则方法
//StringreadTimesStr=jsStr.replaceAll("[^0-9]","");
123456
解析新闻内容
笔者本来是获取新闻内容纯文字的形式,但后来发现Android端也可以显示CSS格式,所以后来内容保留了HTML格式。
ElementcontentEle=articleEle.getElementById("article_content");
//新闻主体内容
StringcontentStr=contentEle.toString();
//如果用text()方法,新闻主体内容的html标签会丢失
//为了在Android上用WebView显示html,用toString()
//StringcontentStr=contentEle.text();123456
解析图片Url
注意一个网页上大大小小的图片很多,为了只获取新闻正文中的内容,我们最好首先定位到新闻内容的Element,然后再利用getElementsByTag(“img”)筛选出图片。
ElementcontentEle=articleEle.getElementById("article_content");
//新闻主体内容
StringcontentStr=contentEle.toString();
//如果用text()方法,新闻主体内容的html标签会丢失
//为了在Android上用WebView显示html,用toString()
//StringcontentStr=contentEle.text();
Elementsimages=contentEle.getElementsByTag("img");
String[]imageUrls=newString[images.size()];
for(inti=0;i imageUrls[i]=images.get(i).attr("src"); }123456789101112 新闻实体类JavaBean 上面获取了新闻的标题、发布日期、阅读次数、新闻内容等等,我们自然需要构造一个javabean,把获取的内容封装进实体类中。 publicclassArticleItem{ privateintindex; privateString[]imageUrls; privateStringtitle; privateStringpublishDate; privateStringsource; privateintreadTimes; privateStringbody; publicArticleItem(intindex,String[]imageUrls,Stringtitle,StringpublishDate,Stringsource,intreadTimes, Stringbody){ this.index=index; this.imageUrls=imageUrls; this.title=title; this.publishDate=publishDate; this.source=source; this.readTimes=readTimes; this.body=body; } @Override publicStringtoString(){ return"ArticleItem[index="+index+",\nimageUrls="+Arrays.toString(imageUrls)+",\ntitle="+title +",\npublishDate="+publishDate+",\nsource="+source+",\nreadTimes="+readTimes+",\nbody="+body +"]"; } }12345678910111213141516171819202122232425262728293031 测试 publicstaticArticleItemgetNewsItem(intcurrentPage)throwsCommonException{ //根据后缀的数字,拼接新闻url StringurlStr=ARTICLE_BASE_URL+currentPage+".html"; StringhtmlStr=HttpTool.doGet(urlStr); Documentdoc=Jsoup.parse(htmlStr); ElementarticleEle=doc.getElementById("article"); //标题 ElementtitleEle=articleEle.getElementById("article_title"); StringtitleStr=titleEle.text(); //article_detail包括了2016-01-15来源: 浏览次数: 177 ElementdetailEle=articleEle.getElementById("article_detail"); Elementsdetails=detailEle.getElementsByTag("span"); //发布时间 StringdateStr=details.get(0).text(); //新闻来源 StringsourceStr=details.get (1).text(); //访问这个新闻页面,浏览次数会+1,次数是JS渲染的 StringjsStr=HttpTool.doGet(COUNT_BASE_URL+currentPage); intreadTimes=Integer.parseInt(jsStr.replaceAll("\\D+","")); //或者使用下面这个正则方法 //StringreadTimesStr=jsStr.replaceAll("[^0-9]",""); ElementcontentEle=articleEle.getElementById("article_content"); //新闻主体内容 StringcontentStr=contentEle.toString(); //如果用text()方法,新闻主体内容的html标签会丢失 //为了在Android上用WebView显示html,用toString() //StringcontentStr=contentEle.text(); Elementsimages=contentEle.getElementsByTag("img"); String[]imageUrls=newString[images.size()]; for(inti=0;i imageUrls[i]=images.get(i).attr("src"); } returnnewArticleItem(currentPage,imageUrls,titleStr,dateStr,sourceStr,readTimes,contentStr); } publicstaticvoidmain(String[]args)throwsCommonException{ System.out.println(getNewsItem(7928)); } 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950 输出信息 ArticleItem[index=7928, imageUrls=[/uploads/image/20160114/20160114225911_34428.png], title=电院2014级开展“让诚信之花开遍冬日校园”教育活动, publishDate=2016-01-14, source=来源: 电影新闻网, readTimes=200, body= 西电新闻网讯(通讯员丁彤王朱丹...) 123456789 展望 本文讲解了如何实现Jsoup网络爬虫,如果文章对您有帮助,感谢捐赠。 最近用MaterialDesign重构了自己的新闻App,新闻数据是利用Jsoup实现的。 第1版爬虫是在手机端实现的(我承认这设计很不好,既费流量又增加客户端负担),后来在新浪云上实现了一个简单的JSP,过滤了原网页的图片、一级栏目等,只返回新闻标题、阅读次数、新闻内容等等。 本文链接转载请注明出处 后期的打算是把爬虫这步移到新浪云上,返回格式化的JSON数据给客户端使用。 可能的话,图片使用七牛CDN(ContentDeliveryNetwork内容分发网络),在云上利用Mysql数据库缓存新闻信息。 参考文章 《Android网络爬虫程序(基于Jsoup)》http: //songlee24.github.io/2015/01/11/android-crawler/ 《抓取csdn上的各类别的文章(制作csdnapp二)》
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- java 实现 爬虫 app 提供 数据 jsoup 网络