您的位置:首页 > 理论基础 > 计算机网络

使用httpclient jsoup 及jetty 全自动登录网站 抓取网页,解析并展示

2012-04-08 10:37 519 查看
前提:因为一直在和朋友做网站 看门猪返利网,使用的程序本身并不能从广告联盟抓取商城数据,一个一个添加几百个都手动也不靠谱,程序员出身就决定出手一试。使用到的开源包:httpclient  做自动登录,网页抓取jsoup 解析网页,获取目标信息,配合httpclient进行尝试网页抓取jetty 抓取到的信息需要展示,使用传统应用程序展示要考虑的东西多,还是网页展示简单,就使用jetty做内嵌。slf4j 用都知道,包小好用。velocity  做网页模板jsoup 也能直接抓取网页,但在cookie维持这一块跟httpclient差远了,所以我就只用jsoup解析抓取的网页。登录:
			HttpClient httpclient = new DefaultHttpClient();//httpclient.getParams().setParameter(HTTP.CONTENT_ENCODING, "UTF-8");String url="http://www.kanmenzhu.com/user/login.php";HttpPost client=new HttpPost(url);List<NameValuePair> nvList=new ArrayList<NameValuePair>(2);nvList.add(new BasicNameValuePair("user","u"));nvList.add(new BasicNameValuePair("password","p"));client.setEntity(new UrlEncodedFormEntity(nvList, "UTF-8"));logger.info("尝试登录"+host);HttpResponse response=httpclient.execute(client);if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){HttpEntity entity = response.getEntity();EntityUtils.consume(entity);logger.info("成功登录"+host);//String res=EntityUtils.toString(entity);//logger.info(res);}else{logger.warn("登录失败");System.exit(0);}
这里有个不完善的是仅判断了http响应,并未判断返回信息是否在业务上成功登录,即用户密码是否正确。这就算完成了登录了,接下来可以使用上面的httpclient来get抓取网页了,不再需要担心未登录的情况。解析:
			logger.info("开始广告分析列表.....");//这是第一页的链接url="http://www.kanmenzhu.com/malllist.php";Document doc=HttpPageTools.getJsoupDocByUrl(httpclient, url+"&p=1");
//这是工具类方法 另一个类中的
public static Document getJsoupDocByUrl(HttpClient httpclient,String url){HttpGet hg=new HttpGet(url);HttpResponse response;try {response = httpclient.execute(hg);if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){HttpEntity entity = response.getEntity();String res=EntityUtils.toString(entity);EntityUtils.consume(entity);//logger.info(res);Document doc=Jsoup.parse(res);return doc;}} catch (Exception e) {e.printStackTrace();}return null;}
//工具类方法
if(doc!=null){int pageCount=MaiPraser.getPageInfo(doc);logger.info("总共:"+pageCount+"页,当前第1页");Map<String, DuoMaiCPS> cpsMap=new HashMap<String, MyCPS>();//放所有广告for(int i=2;i<=pageCount;i++){doc=HttpPageTools.getJsoupDocByUrl(httpclient, url+"&p="+i);//见上面的工具类抓取代码logger.info("总共:"+pageCount+"页,当前第"+i+"页");cpsMap.putAll(MaiPraser.prase(doc,host));//把解析的每一页都加进去}logger.info("广告列表分析完毕,共"+cpsMap.size()+"个广告商,开始分析单个广告商信息.....");//根据解析到的链接,再进入到详页抓信息for(MyCPS dp:cpsMap.values()){String detailLink=dp.getCpsDetail();//logger.info("要抓取的链接:"+detailLink);HttpGet thg=new HttpGet(detailLink);HttpResponse httpResp=httpclient.execute(thg);if(httpResp.getStatusLine().getStatusCode()==HttpStatus.SC_OK){//成功获取到 了Thread.sleep(200);HttpEntity respBody=httpResp.getEntity();//logger.info(EntityUtils.toString(respBody));Document ddoc=Jsoup.parse(EntityUtils.toString(respBody));EntityUtils.consume(httpResp.getEntity());MaiPraser.praseDetail(dp, ddoc, host);//详细解析代码,见解析代码示例
}logger.info("广告商已解析完成:"+dp.getName());MainServlet.addData(dp);// 这是我Servlet 中的一个list}}
解析代码示例:获取总页数信息
	 */public static int getPageInfo(Document doc){Elements elements=doc.select("td[class$=foot_page]");//这就是jsoup语法,很像jqueryString href=elements.first().select("a[class$=page_last]").attr("href");int result=Integer.valueOf((href.substring(href.lastIndexOf("=")+1)));//logger.info(href);return result;}
这是解析图片地址,网址信息的代码,也是类似 juqery语法
	public static void praseDetail(MyCPS dmc,Document doc_detail,String host){for(Element ne:doc_detail.select("div[class$=ad_newteach]")){String u=ne.childNode(1).attr("src");u=host+u;dmc.setImg(u);//图片logger.info(ne.childNode(1).attr("src"));dmc.setName(((Element)ne.childNode(3)).text());//名称logger.info(((Element)ne.childNode(3)).text());dmc.setUrl(((Element)ne.childNode(5)).child(0).attr("href"));//网站logger.info(((Element)ne.childNode(5)).child(0).attr("href"));//String adids=((Element)ne.childNode(7)).child(0).attr("href");//logger.info(adids=adids.substring(adids.lastIndexOf('=')+1));//	MainServlet.addData(ne.childNode(1).toString());//if(ne.tagName().equals("img")){//	logger.info(ne.childNode(0));//}}for(Element ne:doc_detail.select("div[class$=ad_zhu]")){//简介logger.info(ne.text());dmc.setMemo(ne.text());}}
jetty的启动:
public class WebServerStarter {private static Logger logger=LoggerFactory.getLogger(WebServerStarter.class);public static void main(String[] args) {Server server=new Server();Connector conn = new SelectChannelConnector();if(args!=null)conn.setPort(Integer.valueOf(args[0]));server.setConnectors(new Connector[] {conn});WebAppContext webapp = new WebAppContext();webapp.setContextPath("/");webapp.addServlet(new ServletHolder(new MainServlet()), "/*");//MainServlet 就是我的一个servlet,就这么简单。webapp.setWar("./webapps"); //如需指定war目录,则相对应地在工程目录下建立一同名目录,否则启动时会产生异常server.setHandler(webapp);try {server.start();} catch (Exception e) {logger.error("可能是端口冲突了,请检查端口配置",e);System.exit(0);}}}
展示:展示就比较简单了,把信息往VM中一填再展示就行了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐