java爬虫

爬虫思路:

1. 获取网页源代码

2. 分析源代码,从源代码中提取有用的信息(可以用正则,也可以用文档节点获取)

所以根据以上思路在我们的类中应该有两个函数,一个用来获取源代码,另一个用来提取有用的信息。

爬取的是39健康网

获取网页源代码的代码如下:

public static String getHtmlInfoFromUrl(String url, String encoding) {
		StringBuffer sb = new StringBuffer();
		InputStreamReader isr = null;
		try{
			URL urlObj = new  URL(url);
			URLConnection uc = urlObj.openConnection();
			isr = new InputStreamReader(uc.getInputStream(), encoding);
			BufferedReader br = new BufferedReader(isr);
			String line = null;
			while ((line = br.readLine()) != null) {
				sb.append(line + "\n");
			}
		}catch (Exception e) {
			e.printStackTrace();
		}finally {
			try {
				isr.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		String str = sb.toString();
	//System.out.println(str);
		return str;
		
	}
获取了网页源代码之后,我们就应该提取有用的信息了

按F12


可以发现每一个医院的所有信息都对应一个li标签,所以我们只需要找到这里面所有的li标签,也就找到了所有我们需要的信息,当然源代码中可能还有其他的li标签,所以当我们的爬取结果出来了之后还需要对其进行一个筛选

要获取所有li标签,就需要使用以下代码

	org.jsoup.nodes.Document document = Jsoup.parse(html);
	Elements elementList = document.getElementsByTag("li");
这样所有的li标签就在这个elementList里面了。只需要对这个elementList进行遍历就可以取出每一个医院的信息。

接着分析每一个li标签里面的内容,我们要获取的是医院的图片,和医院的名称。


上图可以看到,每一个li标签里面都有一个img标签,这个img标签就是需要获取的图片的信息,包括图片的路径,class,只需要获取到这个图片对象,我们就可以得到他的路径,从而得到图片

同样对与标题每一个医院的标题都包含在yy-msg这个class对应的div下的div下的a标签里面,所以我们只需要根据这个a标签的class=yy-name就可以获得每一个a标签对象,从而获得他的title信息。

所以提取有用信息的函数的代码如下:

/**
	 * @param url  网址
	 * @param encoding 解码方式
	 */
	
	public static List<HashMap<String, String>> getHospitalInfo(String url, String encoding) {
		String html = getHtmlInfoFromUrl(url, encoding);
		org.jsoup.nodes.Document document = Jsoup.parse(html);
		Elements elementList = document.getElementsByTag("li");
		List<HashMap<String, String>> maps =  new ArrayList<HashMap<String, String>>();
		for(org.jsoup.nodes.Element element: elementList){
			String img = element.getElementsByClass("yy-img").attr("src");
			String title = element.getElementsByClass("yy-name").attr("title");
			if(img != "" && title != "") {//筛选li标签
				HashMap<String, String> map = new HashMap<String, String>();
				map.put("img", img);
				map.put("title", title);
				maps.add(map);
			}
		}
		return maps;
	}
需要导入的包有:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.jsoup.Jsoup;
import org.jsoup.select.Elements;
主函数测试:

public static void main(String[] args) {
		List<HashMap<String, String>> list = getHospitalInfo("http://yyk.39.net/shanxi2/hospitals/", "gbk");
		for(HashMap<String, String> map: list) {
			System.out.println("图片 :" + map.get("img"));
			System.out.println("医院名称:" + map.get("title"));
			System.out.println("------------------------------------");
		}
	}



jsp页面测试:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import = "com.baidu.parse.util.ParseData" %>
<%@ page import = "java.util.*" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<% 
	List<HashMap<String, String>> list = new ParseData().getHospitalInfo("http://yyk.39.net/shanxi2/hospitals/", "gbk");
	for(HashMap<String, String> map: list) {
		out.print("<img src = " + map.get("img")+">");
		out.print("<p>" + map.get("title") + "</p>");
}

%>
</body>
</html>







最近一直在研究爬虫和Lucene,虽然开始决定选用Heritrix来执行爬虫操作,但是后来发现用它来做还是存在一定的问题,比如需要程序生成相应的XML文件,对于同一个Job,怎样才能保证重复运行该Job时文件夹始终是同一个(Heritrix为Job创建文件夹的规则是“Job名称-时间戳”)等等,都是需要考虑的问题,最终还是将其搁浅。    后来google了一下,找到了一个简单爬虫的程序代码(http://www.blogjava.net/Jack2007/archive/2008/03/24/188138.html),随即试验了一下,发现确实能得到网页的内容,在这里还是要谢谢代码的提供者——Jack.Wang。    虽然试验成功,但是在随后的大数据量试验时,还是出现了问题。最初试验时,我只是让程序去抓取10个URL链接,当我将URL链接数改为100个时,问题出现了——URL中存在重复,而且非常容易的就变成死循环。举个例子来说,比如我首先爬的是A.html,在A.html中有两个链接:B.html,C.html,等爬完A.html以后,程序会爬B.html,这时如果B.html中的所有链接中有A.html这个页面的链接,那么程序又会去爬A.html这个页面,如此一来就形成了一个死循环,永远也不能停止。    跟踪程序发现,原来是在添加要抓取的网页的链接列表中,没有将已经抓取过的URL去除,所以才造成了死循环。现在虽然加上了这个判断,但是从我运行程序的效果来看,也不是很理想,总是感觉有些慢,800个页面要一两分钟才能爬完,这个我觉得有点说不过去。    这个产品,做到现在,我遇到了这么几个情况,有和大家分享的,也有向大家请教,求助的。    1.关于对应关系数据的保存方式    在创建索引的时候,需要将网页的URL和网页的内容传到相应的方法中,当然URL和内容是要对应的,也许是经验太少吧,我采取的是通过构建一个JavaBean的方式来传递的,不知道大家有没有更好的方法       2.关于要创建索引的内容的保存方式    最初的想法是不创建文件,直接将内容保存到变量中,然后创建索引,即先抓取网页的内容,然后将网页的内容和URL保存到自己构建的JavaBean对象中,接着将这个对象放到一个list列表中,等所有网页抓取完毕以后,将这个列表传到创建索引的方法中。这种做法看似不错,可是当URL数量很大时,会导致内存不够用,所以还是创建文件比较稳妥。    3.关于网页编码问题    遇到这个问题也是一个巧合,本来我抓取的是客户的一个网站,后来同事说如果客户看访问日志,这个月的数据会和平常的数据不一样,所以我就抓取公司的网站,结果,问题出现了。原先公司的网站是用GB2312编码做的页面,现在采用的是UTF-8的编码,虽然我已经判断了页面的编码,可是依然不能解决保存的文件中文乱码的问题,不知道大家有什么好办法没有。错误信息为:java.io.UnsupportedEncodingException    附件为爬虫代码 本文出自 “徘徊在c#,java,php之间” 博客,请务必保留此出处http://jerrysun.blog.51cto.com/745955/221879
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值