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


前提:因为一直在和朋友做网站 看门猪返利网 ,使用的程序本身并不能从广告联盟抓取商城数据,一个一个添加几百个都手动也不靠谱,程序员出身就决定出手一试。


使用到的开源包:

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 nvList=new ArrayList(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 cpsMap=new HashMap();//放所有广告
				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语法,很像jquery
		String 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中一填再展示就行了

你可能感兴趣的:(jsoup,string,exception,servlet,webapp,class,url)