SEO优化之根据网址自动生成sitemap.xml文件

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37358860/article/details/79085526

背景:

    公司要做一个电商的网站,而该项目是由J2EE架构完成,项目经理说要让Java代码自助每天生成电子商务网站的Sitemap文件,然后开始上网各种查资料!!!
    然而,终于碰上了本人有生以来第一个在网上没找到的具体答案的东西,自己干吧,不过网上也有做过类似的,只不过人家应该是大牛吧,没有说的很详细,只好自己慢慢领悟了.
    按照大牛给的方向,摆在我面前一下出现三个问题:1,获取网站所有链接。 2,生成XML文件 3,定时调用,后两种问题如果做过Java程序的人,应该比较好解决。(这句话是大牛说的),这篇文章解决的是第一个问题和第二个问题,如何获得网站的所有链接并生成sitemap.xml文件

代码:

package com.langgufoeng.test.entity;
/**
 * 标题: urlEntity.java
 * 路径: com.langgufoeng.test.entity
 * 描述: TODO sitemap.xml中每个链接对应的实体
 * 作者: 郎国峰
 * 时间: 2018-1-7 下午2:50:08
 * 版本: @version V1.0
 */
public class UrlEntity {
    private String loc;
    private String lastmod;
    private String changefreq;
    private String priority;
    public String getLoc() {
        return loc;
    }
    public void setLoc(String loc) {
        this.loc = loc;
    }
    public String getLastmod() {
        return lastmod;
    }
    public void setLastmod(String lastmod) {
        this.lastmod = lastmod;
    }
    public String getChangefreq() {
        return changefreq;
    }
    public void setChangefreq(String changefreq) {
        this.changefreq = changefreq;
    }
    public String getPriority() {
        return priority;
    }
    public void setPriority(String priority) {
        this.priority = priority;
    }
    @Override
    public String toString() {
        return "UrlEntity [loc=" + loc + ", lastmod=" + lastmod
                + ", changefreq=" + changefreq + ", priority=" + priority + "]";
    }
}
package com.langgufoeng.test.entity;

import java.util.List;

/**
 * 标题: UrlsetEntity.java 
 * 路径: com.langgufoeng.test.entity 
 * 描述: TODO sitemap.xml对应的实体 
 * 作者: 郎国峰 
 * 时间: 2018-1-7 下午2:51:15 版本: @version V1.0
 */
public class UrlsetEntity {
    static List<UrlEntity> list;

    public static List<UrlEntity> getList() {
        return list;
    }

    public static void setList(List<UrlEntity> list) {
        UrlsetEntity.list = list;
    }


}
package com.langgufoeng.test;

import java.io.File;
import java.net.MalformedURLException;
import java.util.Date;
import java.util.List;

import com.langgufoeng.test.entity.UrlEntity;
import com.langgufoeng.test.entity.UrlsetEntity;
import com.redfin.sitemapgenerator.ChangeFreq;
import com.redfin.sitemapgenerator.WebSitemapGenerator;
import com.redfin.sitemapgenerator.WebSitemapUrl;

/**
 * 标题: EntityToSitemap.java
 * 路径: com.langgufoeng.test
 * 描述: TODO 根据实体类生成sitemap
 * 作者: 郎国峰
 * 时间: 2018-1-7 下午3:00:01
 * 版本: @version V1.0
 */
public class EntityToSitemap {
    static public void toSitemap(){
        WebSitemapGenerator sitemapGenerator = null;
        try {
            // 压缩输出  true  不压缩输出false
             sitemapGenerator = WebSitemapGenerator.builder("http://www.baidu.com", new File("WebRoot")).gzip(false).build();
            //得到sitemap实体
             List<UrlEntity> sitemapList = UrlsetEntity.getList();
            //遍历实体,得到sitemapUrl信息
            for (int i = 0; i < sitemapList.size(); i++) {
                UrlEntity sitemap = sitemapList.get(i);
                System.out.println("url路径"+sitemap.getLoc());
                WebSitemapUrl sitemapUrl = new WebSitemapUrl.Options(sitemap.getLoc()).build();
                sitemapGenerator.addUrl(sitemapUrl);
            }
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            sitemapGenerator.write();
        }
    }
}
package com.langgufoeng.test;


import java.util.HashSet;
import java.util.Set;

import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.Parser;
import org.htmlparser.filters.NodeClassFilter;
import org.htmlparser.filters.OrFilter;
import org.htmlparser.tags.LinkTag;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;
/**
 * 标题: HtmlParserTool.java 
 * 路径: com.langgufoeng.test 
 * 描述: TODO 从获得的网页中提取url 
 * 作者: 郎国峰 
 * 时间: 2018-1-7 上午10:32:37 
 * 版本: @version V1.0
 */
public class HtmlParserTool {
    private HtmlParserTool(){}
    private static final HtmlParserTool htmlParserTool = new HtmlParserTool();
    /*
     * 单例模式
     */
    public static HtmlParserTool getInstance() {
        return htmlParserTool;
    }
    /**
     * @方法名: extracLinks
     * @描述: 获取一个网站上的链接,filter用来过滤链接
     * @作者: 郎国峰
     * @时间: 2018-1-7 上午10:48:51
     * @return 返回页面上解析出来的集合
     */
    public static Set<String> extracLinks(String url, LinkFilter filter) {
        //创建一个set集合,用来存储页面上解析出来的符合标准的url
        Set<String> links = new HashSet<String>();
        try {
            Parser parser = new Parser(url);
            parser.setEncoding("UTF-8");
            //System.out.println("根据url得到的解析结果"+parser);
            //过滤<frame> 标签的filter
            NodeFilter frameFilter = new NodeFilter() {
                public boolean accept(Node node) {
                    if (node.getText().startsWith("frame src=")){
                        return true;
                    }
                    return false;
                }
            };
            //OrFilter 用来设置过滤<a> 标签和<frame> 标签
            OrFilter linkFilter = new OrFilter(new NodeClassFilter(LinkTag.class), frameFilter);
            //得到所有经过过滤的标签
            NodeList list = parser.extractAllNodesThatMatch(linkFilter);
            //System.out.println("所有经过过滤的标签"+list+"\t list长度:"+list.size());
            for (int i = 0; i < list.size(); i++) {
                Node tag = list.elementAt(i);
                //System.out.println(tag+"每一个标签");
                //判断是否是     <a> 标签
                if (tag instanceof LinkTag) {
                    LinkTag link = (LinkTag) tag;
                    //得到a标签的href
                    String linkUrl = link.getLink();
                    //判断a标签的href的值是否是本网站的,如果是就添加到links中
                    if (filter.accept(linkUrl)){
                        links.add(linkUrl);
                    }
                } else {//<frame>标签
                    //提取frame里的src属性的链接, 如 <frame src="test.html"/>
                    String frame = tag.getText();
                    int start = frame.indexOf("src=");
                    if (start != -1) {
                        frame = frame.substring(start);
                    }

                    int end = frame.indexOf(" ");

                    String frameUrl = "";
                    if (end == -1) {
                        end = frame.indexOf(">");
                        if (end - 1 > 5) {
                            frameUrl = frame.substring(5, end - 1);
                        }
                    }
                    if (filter.accept(frameUrl)) {
                        links.add(frameUrl);
                    }
                }
            }

        } catch (ParserException e) {
            e.printStackTrace();
        }
        return links;
    }
}
package com.langgufoeng.test;
/**
 * 标题: LinkFilter.java
 * 路径: com.langgufoeng.test
 * 描述: TODO 定义一个网址过滤器,判断是否以固定网址开头
 * 作者: 郎国峰
 * 时间: 2018-1-8 下午5:05:47
 * 版本: @version V1.0
 */
public interface LinkFilter {
     public boolean accept(String url);
}
package com.langgufoeng.test;

import java.util.HashSet;
import java.util.Set;

/**
 * 标题: LinkQueue.java
 * 路径: com.langgufoeng.test
 * 描述: TODO 除了URL队列之外,在爬虫过程中,还需要一个数据结构来记录已经访问过的URL.
 *      每当访问一个URL的时候,首先在这个数据结构中进行查找,如果当前URL已经存在,则丢
 *      弃它,这个数据结构要有两个特点:
 *      ~ 结构中保存的URL不能重复
 *      ~ 能够快速的查找(实际系统中URL的数目非常多,因此要考虑查找性能).
 *      针对以上两点,我们选择HashSet作为存储结构
 * 作者: 郎国峰
 * 时间: 2018-1-7 上午8:58:04
 * 版本: @version V1.0
 */
public class LinkQueue {
    //已访问的url集合
    private static Set visitedUrl = new HashSet();
    //待访问的url集合
    private static Queue unVisitedUrl = new Queue();
    //单例
    private final static LinkQueue linkQueue = new LinkQueue();
    private  LinkQueue(){}
    public static LinkQueue getInstance(){
        return linkQueue; 
    }
    /**
     * @方法名: getUnVisitedUrl   
     * @描述: 获得将要访问的URL队列
     * @作者: 郎国峰
     * @时间: 2018-1-7 上午9:06:21
     * @return
     */
    public static Queue getUnVisitedUrl(){
        return unVisitedUrl;
    }
    /**
     * @方法名: addVisitedUrl   
     * @描述: 添加到访问过的URL队列中
     * @作者: 郎国峰
     * @时间: 2018-1-7 上午9:07:47
     * @param url
     */
    public static void addVisitedUrl(String url){
        visitedUrl.add(url);
    }
    /**
     * @方法名: removeVisitedUrl   
     * @描述: 移出访问过的url
     * @作者: 郎国峰
     * @时间: 2018-1-7 上午9:09:40
     * @param url
     */
    public static void removeVisitedUrl(String url){
        visitedUrl.remove(url);
    }
    /**
     * @方法名: unVisitedUrlDeQueue   
     * @描述: 未访问过的url出队列
     * @作者: 郎国峰
     * @时间: 2018-1-7 上午9:12:20
     * @return
     */
    public static Object unVisitedUrlDeQueue(){
        return unVisitedUrl.deQueue();
    }
    /**
     * @方法名: addUnvisitedUrl   
     * @描述: 保证每个url只被访问一次
     * @作者: 郎国峰
     * @时间: 2018-1-7 上午9:19:26
     * @param url
     */
    public static void addUnvisitedUrl(String url){
        if(url != null && !url.trim().equals("") //url不为null也不为空
                && !visitedUrl.contains(url)     //url未被访问过
                && !unVisitedUrl.contians(url)){ //url队列里不包含此url
            unVisitedUrl.enQueue(url);           //将此url添加到url队列中
        }
    }
    /**
     * @方法名: getVisitedUrlNum   
     * @描述: 获得已经访问过的URL数目
     * @作者: 郎国峰
     * @时间: 2018-1-7 上午9:21:02
     * @return
     */
    public static int getVisitedUrlNum(){
        return visitedUrl.size();
    }
    /**
     * @方法名: unVisitedUrlsEmpty   
     * @描述: 判断未访问过的url是否为空
     * @作者: 郎国峰
     * @时间: 2018-1-7 上午9:24:03
     * @return
     */
    public static boolean unVisitedUrlsEmpty(){
        return unVisitedUrl.isQueueEmpty();
    }
    /**
     * @方法名: getVisitedUrl   
     * @描述: 获得已经访问过的URL集合
     * @作者: 郎国峰
     * @时间: 2018-1-7 下午3:23:46
     * @return
     */
    public static Set getVisitedUrl() {
        return visitedUrl;
    }





}
package com.langgufoeng.test;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import com.langgufoeng.test.entity.UrlEntity;
import com.langgufoeng.test.entity.UrlsetEntity;
 /**
  * 标题: MainCrawler.java
  * 路径: com.langgufoeng.test
  * 描述: TODO 生成sitemap.xml主程序
  * 作者: 郎国峰
  * 时间: 2018-1-7 下午1:52:36
  * 版本: @version V1.0
  */
public class MainCrawler { 

    private LinkQueue linkQueue = LinkQueue.getInstance();
    /**
     * @方法名: initCrawlerWithSeeds   
     * @描述: 使用种子初始化RUL队列
     * @作者: 郎国峰
     * @时间: 2018-1-7 下午1:53:13
     * @param seeds
     */
    private void initCrawlerWithSeeds(String[] seeds) {  
        for(int i=0; i<seeds.length; i++) {  
            linkQueue.addUnvisitedUrl(seeds[i]);  
        }  
    }  
    /**
     * @方法名: crawling   
     * @描述: 根据提供的种子进行抓取所有页面
     * @作者: 郎国峰
     * @时间: 2018-1-7 下午1:56:17
     * @param seeds
     */
    public void crawling(String[] seeds) {  
        //定义过滤器,提取以 www.baidu.com 开始的链接
        LinkFilter filter = new LinkFilter() {  
            public boolean accept(String url) {  
                if(url.startsWith("http://www.baidu.com")) {  
                    return true;  
                }  
                return false;  
            }  
        }; 
        int i = 0;
        //初始化URL队列  
        initCrawlerWithSeeds(seeds);  
        //循环抓取页面        循环条件:待抓取的链接不空且抓取的页面不超过1000个
        while(!linkQueue.unVisitedUrlsEmpty() && linkQueue.getVisitedUrlNum()<=1000) { 
            //队头URL出队列
            String visitUrl = (String) linkQueue.unVisitedUrlDeQueue();  
            if(visitUrl == null) { //如果没有未被访问过的url,将终止循环 
                continue;  
            }  
            System.out.println("url:"+visitUrl);
            DownLoadFile downLoader = new DownLoadFile();  
            //下载网页
            //downLoader.downloadFile(visitUrl); 
            //将该url放入已访问的url中
            linkQueue.addVisitedUrl(visitUrl);  
            //提取出下载网页中的url 
            Set<String> links = HtmlParserTool.extracLinks(visitUrl, filter); 
            System.out.println("再次提取的页面路径"+links);
            for(String link:links) {  
                linkQueue.addUnvisitedUrl(link);  
            }
            System.err.println("-------------------------------循环"+ ++i+"次------------------------------");
        }  
    }  

    public static void main(String[] args) { 
        //声明一个网站地址字符串
        //创建一个爬虫主线程
        MainCrawler crawler = new MainCrawler();  
        crawler.crawling(new String[]{"http://www.baidu.com"}); //NewFile main
        //将所有访问过的链接放到一个set里
        Set set = LinkQueue.getVisitedUrl();
        //创建一个list用来存储sitemap信息
        List<UrlEntity> list = new ArrayList<UrlEntity>();
        //遍历所有访问过的链接,得到对应的sitemap信息,赋值给url实体
        for (Object object : set) {
             UrlEntity url = new UrlEntity();
             url.setLoc(object.toString());
             list.add(url);
        }
        //将url实体集合赋值给urlset实体
        UrlsetEntity.setList(list);
        //创建sitemap文件
        EntityToSitemap.toSitemap();
    }  
}  
package com.langgufoeng.test;

import java.util.LinkedList;

/**
 * 标题: Queue.java
 * 路径: com.langgufoeng.test
 * 描述: TODO 队列,保存将要访问的URL
 * 作者: 郎国峰
 * 时间: 2018-1-7 上午8:49:29
 * 版本: @version V1.0
 */
public class Queue {
    //使用链表实现队列
    private LinkedList queue = new LinkedList();
    /**
     * @方法名: enQueue   
     * @描述: 入队列
     * @作者: 郎国峰
     * @时间: 2018-1-7 上午8:52:02
     * @param t
     */
    public void enQueue(Object t){
        queue.addLast(t);
    }
    /**
     * @方法名: deQueue   
     * @描述: 出队列
     * @作者: 郎国峰
     * @时间: 2018-1-7 上午8:53:13
     * @return
     */
    public Object deQueue(){
        return queue.removeFirst();
    }
    /**
     * @方法名: isQueueEmpty   
     * @描述: 判断队列是否为空
     * @作者: 郎国峰
     * @时间: 2018-1-7 上午8:54:17
     * @return
     */
    public boolean isQueueEmpty(){
        return queue.isEmpty();
    }
    /**
     * @方法名: contians   
     * @描述: 判断队列是否包含t
     * @作者: 郎国峰
     * @时间: 2018-1-7 上午8:55:35
     * @param t
     * @return
     */
    public boolean contians(Object t){
        return queue.contains(t);
    }


}

注意:

以上代码是我自己写的一个例子,用的是myeclipse,测试的百度首页,解析的连接知识a标签和frame标签的连接,如果项目需要可以参考,然后按实际需求进行相应的更改

猜你喜欢

转载自blog.csdn.net/qq_37358860/article/details/79085526