利用jsoup爬虫优酷、土豆等视频网站rss利用solr创建索引

1、前提:

了解jsoup、solr等相关的技术、会搭建solr

2、我将爬虫的网站都写在一个xml中,所以先要解析这个xml,得到其网址,然后定时去爬虫

package com.tmzs.pc.jsoup;

import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Timer;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.tmzs.pc.entity.InfoXml;
/**
 * @功能 定时器,定时的爬虫
 * @author admin
 *
 */
public class TestTimer {
	public static final List<InfoXml> infoList = new ArrayList<InfoXml>() ;
	public static void main(String[] args) throws Exception {
		parseXml() ;
		MyTask myTask = new MyTask();
        Timer timer = new Timer();
        timer.schedule(myTask, 4000, 1000*60*5);   //4000后执行,每次间隔1000*60*5=5分钟
	}

	/**
	 * @功能 解析XML
	 * @throws Exception
	 */
	private static void parseXml() throws Exception {
		SAXReader reader = new SAXReader();  
		Document  document = reader.read(new File("e:/Channel.xml"));  
		Element root = document.getRootElement();  //获取根节点
		List<Element> nodes = root.elements("tree");  
		
	    for (Iterator it = nodes.iterator(); it.hasNext();) {  
	    	Element tree = (Element) it.next();  
	    	List<Element> channels = tree.elements("channel");  
	    	
	    	//Channel
	    	for (Iterator ite = channels.iterator(); ite.hasNext();) {  
	 	    	Element channel = (Element) ite.next();  
	 	    	InfoXml ix = new InfoXml() ;
		    	ix.setTreeName(tree.attributeValue("name")) ;
		    	ix.setTreeOpen(Integer.parseInt(tree.attributeValue("open"))) ;
		    	
	 	    	ix.setChannelName(channel.element("name").getTextTrim()) ;
	 	    	ix.setChannelLink(channel.element("link").getTextTrim()) ;
	 	    	ix.setChannelType(channel.element("type").getTextTrim()) ;
	 	    	ix.setChannelAllNewsNum(Integer.parseInt(channel.element("AllNewsNum").getTextTrim())) ;
	 	    	ix.setChannelMaxNewsNum(Integer.parseInt(channel.element("MaxNewsNum").getTextTrim())) ;
	 	    	ix.setChannelTTU(Integer.parseInt(channel.element("TTU").getTextTrim())) ;
	 	    	ix.setChannelUnReadNewsNum(Integer.parseInt(channel.element("UnReadNewsNum").getTextTrim())) ;
	 	    	infoList.add(ix) ;
	 	    } 
	    	
	    } 

		for(int i=0;i<infoList.size();i++){
			InfoXml ix = infoList.get(i) ;
			System.out.println("getTreeName="+ix.getTreeName()+",getChannelName="+ix.getChannelName()
					+",channelType="+ix.getChannelType()+",link="+ix.getChannelLink());
		}
		
	}
}

3、执行定时器的方法,即爬虫。但是要考虑一个问题,爬虫的内容是否会重复。这里我是弄了连个Map,将爬虫的视频标题(title)放入Map里面作为Key。然后做了一个循环,当10次后爬虫的数据的title在Map里面没有,就清楚Map,说的不好,请看代码:

还有一点就是<link>标签得不到,所以我借助了rssjlib.jar

package com.tmzs.pc.jsoup;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimerTask;

import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.common.SolrInputDocument;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import com.rsslibj.elements.Channel;
import com.rsslibj.elements.Item;
import com.rsslibj.elements.RSSReader;
import com.tmzs.pc.entity.InfoXml;
import com.tmzs.pc.entity.Video;
import com.tmzs.pc.jdbc.JdbcAction;

/**
 * @功能 爬虫
 * @author admin
 *
 */
public class MyTask extends TimerTask{
	/**
	 * @功能 循环遍历XML
	 */
	private static Channel channel;    //RSS实体  
	Document doc = null;  
	Map oldMap = new HashMap();     
	Map newMap = new HashMap(); 
	int index = 1 ;
	int oldZeroNum = 0 ;
	boolean flag = true ;
    public void run(){
    	List<InfoXml> urls = TestTimer.infoList ;
    	    
    	int zeroNum = 0 ;
    	for(int j=0;j<urls.size();j++){
    		InfoXml ix = urls.get(j) ;
    		String url = ix.getChannelLink();  
    		URL ur;
    		List<Item> items = null ;
			try {
				ur = new URL(url);
				InputStream inputstream = ur.openStream();  
	            BufferedReader reader = null;  
	            //由于百度编码不是UTF-8,所以你懂得
	            if("百度".equals(ix.getTreeName())){
	            	flag = true ;
	            	reader = new BufferedReader(new InputStreamReader(inputstream,"GB2312")); 
	            }else{
	            	flag = false ;
	            	reader = new BufferedReader(new InputStreamReader(inputstream)); 
	            }
	            StringBuilder data = new StringBuilder();  
	            String line = null;  
	            while( (line = reader.readLine()) != null ) {  
	                data.append(line);  
	            }  
	              
	            reader.close();  
	            inputstream.close();  
	            //解析字符串  
	            StringReader read = new StringReader(data.toString());  
	            System.out.println("data.toString()="+data.toString());
	            
	            doc = Jsoup.parse(data.toString());
	           
	            // 创建RSS阅读对象的  
	            RSSReader rssReader = new RSSReader();  
	            // 设置读取内容  
	            rssReader.setReader(read);
	              
	            channel = rssReader.getChannel(); 
	            items = channel.getItems();
			} catch (MalformedURLException e1) {
				e1.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (electric.xml.ParseException e) {
				e.printStackTrace();
			}  
     	    
    	    Elements element = doc.getElementsByTag("channel");
    	    Elements elems = doc.getElementsByTag("item");  
    	    for(int i=0;i<elems.size();i++){
    	    	Item item = items.get(i) ;
    	    	Element elem = elems.get(i) ;
    	    	Elements title = elem.getElementsByTag("title") ;
    	    	if(index == 1){
    	    		oldMap.put(title.html(), 1) ;
    	    		//保存数据
    	    		insertData(element,elem,ix,channel,item) ;
    	    	}else if(index > 1){
    	    		if(oldMap.containsKey(title.html())){
    	    			zeroNum ++ ;
    	    		}else{
    	    			if(!newMap.containsKey(title.html())){
    	    				newMap.put(title.html(), 1) ;
    	    				insertData(element,elem,ix,channel,item) ;
    	    			}
    	    		}
    	    		
    	    	}
    	    }
    	}
    	//判断是否清楚Map
    	if(zeroNum == 0){
    		oldZeroNum++;
    		if(oldZeroNum == 10){
    			oldMap.clear();
    			oldZeroNum = 0;
    			oldMap = newMap;
    			newMap.clear();
    		}
    	}
    	index++ ;
    }
    
    /**
     * @功能 保存数据
     * @param element
     * @param elem
     */
    private void insertData(Elements element, Element elem, InfoXml ix,Channel channel,Item item) {
    	String sourceLink = channel.getLink() ;
    	String itemLink = item.getLink() ;
  	    
    	Elements sourceTitle = element.get(0).getElementsByTag("title") ;
// 	    Elements sourceLink = element.get(0).getElementsByTag("link") ;
 	    Elements sourceDesc = element.get(0).getElementsByTag("description") ;
 	    Elements sourceImageUrl = element.get(0).getElementsByTag("url") ;
 	   
    	Elements title = elem.getElementsByTag("title") ;
    	Elements guid = elem.getElementsByTag("guid") ;
 //   	Elements link = elem.getElementsByTag("link") ;
    	Elements description = elem.getElementsByTag("description") ;
    	Elements duration = elem.getElementsByTag("itunes:duration") ;
    	Elements keyword = elem.getElementsByTag("itunes:keywords") ;
    	Elements author = elem.getElementsByTag("author") ;
    	Elements pubDate = elem.getElementsByTag("pubDate") ;
    	Elements enclosure = elem.getElementsByTag("enclosure") ;
    	Elements itemSource = elem.getElementsByTag("source") ;  //条目源,如:百度中新闻来自新闻网
    	String itemFileType = enclosure.attr("type") ;
    	String itemFileLink = enclosure.attr("url") ;
    	SimpleDateFormat sf = new SimpleDateFormat("EEE, dd MMM yyyy hh:mm:ss z",Locale.ENGLISH);
    	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") ;
    	String itemDate = "";
        try {
        	if(!flag){
        		java.util.Date d = sf.parse(pubDate.html());
    			itemDate = sdf.format(d) ;
        	}else{
        		itemDate = pubDate.html().replaceAll("T", " ").replaceAll(".000Z", "") ;
        	}
			
		} catch (ParseException e) {
			e.printStackTrace();
		}
		int itemDuration = 0 ;
		if(!"".equals(duration.html())){
			itemDuration = parseDate(duration.html()) ;
		}
		
    	Video v = new Video() ;
    	v.setId(new Date().getTime()+"") ;
    	v.setTypeName(ix.getChannelType()) ;
    	v.setClassName(ix.getTreeName()+"_"+ix.getChannelName()) ;
    	
    	v.setSourceDesc(sourceDesc.first().html()) ;
    	if(sourceImageUrl.first()!=null){
    		v.setSourceImageLink(sourceImageUrl.first().html()) ;
    	}else{
    		v.setSourceImageLink("") ;
    	}
    	v.setSourceLink(sourceLink) ;
    	v.setSourceTitle(sourceTitle.first().html()) ;
    	
    	v.setItemDate(sdf.format(new Date())) ;				//solr处理时间
    	v.setItemTitle(title.html()) ;
    	v.setItemLink(itemLink) ;
    	
		v.setItemPubDate(itemDate) ;
		
		v.setItemDesc(description.html()) ;
    	v.setItemAuthor(author.html()) ;
    	v.setItemSource(itemSource.html()) ;  //条目源,如:百度中新闻来自新闻网
    	v.setItemKeyword(keyword.html()) ;
    	v.setItemDuration(itemDuration) ;
    	v.setItemGuid(guid.html()) ;
    	v.setItemFileLink(itemFileLink) ;
    	v.setItemFileType(itemFileType) ;
		
		v.setState(400) ;
		writerSolr(v) ;
//		JdbcAction.insert(v) ;
	}

    /**
     * @功能 写进索引
     */
    public void writerSolr(Video v) {
        // TODO Auto-generated method stub
         try {
              //获取连接服务
             HttpSolrServer solrServer= SolrServer.getInstance().getServer();
              SolrInputDocument doc1 = new SolrInputDocument();
              doc1.addField("id", v.getId());
              doc1.addField("typename", v.getTypeName());
              doc1.addField("classname", v.getClassName());
              doc1.addField("itemauthor", v.getItemAuthor());
              doc1.addField("itemdate", v.getItemDate());
              doc1.addField("itemdesc", v.getItemDesc());
              doc1.addField("itemduration", v.getItemDuration());
              
              doc1.addField("itemfilelink", v.getItemFileLink());
              doc1.addField("itemfiletype", v.getItemFileType());
              doc1.addField("itemguid", v.getItemGuid());
              doc1.addField("itemkeyword", v.getItemKeyword());
              doc1.addField("itemlink", v.getItemLink());
              
              doc1.addField("itempubdate", v.getItemPubDate());
              doc1.addField("itemsource", v.getItemSource());
              doc1.addField("itemtitle", v.getItemTitle());
              doc1.addField("sourcedesc", v.getSourceDesc());
              doc1.addField("sourceimagelink", v.getSourceImageLink());
              doc1.addField("sourcelink", v.getSourceLink());
              doc1.addField("sourcetitle", v.getSourceTitle());
              
              solrServer.add(doc1);
              solrServer.commit();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * @功能 将形如XX:XX的时间转为秒数
     * @param html
     * @return
     */
	private static int parseDate(String duration) {
		int itemDuration = 0 ;
		SimpleDateFormat sdf = new SimpleDateFormat("mm:ss") ;
		try {
			Date d = sdf.parse(duration) ;
			itemDuration = d.getMinutes()*60+d.getSeconds() ;
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return itemDuration;
	}

	public static void main(String[] args) throws Exception {
		SimpleDateFormat sf = new SimpleDateFormat("EEE, dd MMM yyyy hh:mm:ss z",Locale.ENGLISH);
    	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") ;
    	SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ") ;
    	String itemDate = "";
        try {
			java.util.Date d = sf.parse("Mon, 19 Mar 2012 10:36:17 +0800");
			
			System.out.println(sd.parse("2013-12-04T08:08:45.000Z"));
			itemDate = sdf.format(d) ;
		} catch (ParseException e) {
			e.printStackTrace();
		}
		System.out.println(sdf.parse(itemDate)); 
	}
}

4、爬完之后,在solr页面可以看到


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值