java sitemap.xml站点地图创建 sitemap提交百度提示xml格式错误 sitemapgen4j使用 java百度链接主动(实时)推送

一、前言

 

前几个月用jeesite4开发了个网站,上线运行了几个月,因为自己搞过SEO,所有,想把站点提交到百度收录,遇到了一些很尴尬的事,就是百度链接提交通过sitemap提交,一直提示XML格式错误,提示这个也就算了,问题是没有任何错误信息,无语。。

java sitemap.xml站点地图创建 sitemap提交百度提示xml格式错误 sitemapgen4j使用 java百度链接主动(实时)推送_第1张图片

检查了好几遍,没有任何问题,上面提示着XML错误,点击去就提示网页找不到。。

java sitemap.xml站点地图创建 sitemap提交百度提示xml格式错误 sitemapgen4j使用 java百度链接主动(实时)推送_第2张图片

本来想着反馈下问题,没想到,百度那边半个多月了没有答案。。

java sitemap.xml站点地图创建 sitemap提交百度提示xml格式错误 sitemapgen4j使用 java百度链接主动(实时)推送_第3张图片

自己也不急,没事就等等呗,直到今天晚上,有时间了,把他解决掉了,解决思路,用的是测试法,先将百度提供的示例完整的复制一份放到服务器上,改下链接,再次提交,百度就没有提示xml格式错误了。。。出错的原因很简单。。。。就是sitemap索引文件格式有问题。。以下是我生成sitemap索引文件的格式:

问题就出在xml命名空间。。在百度的示例中,没有用命名空间。。用了会报错。这。。

java sitemap.xml站点地图创建 sitemap提交百度提示xml格式错误 sitemapgen4j使用 java百度链接主动(实时)推送_第4张图片

 

关于xml格式错误的注意点:

 

1.最后现将百度提供的示例,复制一份,将loc改成自己的链接,测试下。

2.xml格式要utf-8格式,我用大写UTF-8测试了一下。。也报xml格式错误。。

3.示例中的lastmod说是选填,我这里如果没有的话,貌似还是会报xml格式错误。

4.还有个比较奇怪的问题就是。。xml格式的缩进。。在vim中查看下缩进。

 

先说下什么是sitemap?

 

Sitemap是站长告诉搜索引擎他们网站上可供抓取的网页有哪些。最简单的Sitemap形式就是XML文件。在其中列出网站中的网址以及关于每个网址的其他元数据(上次更新的时间、更改的频率以及相对于网站上其他网址的重要程度为何等),以便搜索引擎可以更加智能地抓取网站。

 

百度的链接提交总的分为两种:

1.自动提交:自动提交又分为三种,实时,自动,sitemap,我这里用的是主动推送+sitemap两种组合方式。

2.手动提交

java sitemap.xml站点地图创建 sitemap提交百度提示xml格式错误 sitemapgen4j使用 java百度链接主动(实时)推送_第5张图片
 

二、操作

 

A.主动推送

 

主动推送比较简单,就是将你想要提交的链接通过POST提交到百度就行了,代码如下,比较简单,通过URLConnection提交:

    /**
     * 从百度站长平台获取
     */
    private static String baiduApiUrl = "http://data.zz.baidu.com/urls?site=www.xxxx.com&token=xxxx";
    /**
     * 百度链接实时推送
     * @param Parameters
     * @return
     */
    public static String Post(String[] Parameters){
        if(null == Parameters || Parameters.length ==0){
            return null;
        }
        String result="";
        PrintWriter out=null;
        BufferedReader in=null;
        OutputStreamWriter outs = null;
        try {
            //建立URL之间的连接
            URLConnection conn=new URL(baiduApiUrl).openConnection();
            //设置通用的请求属性
            conn.setRequestProperty("Host","data.zz.baidu.com");
            conn.setRequestProperty("User-Agent", "curl/7.12.1");
            conn.setRequestProperty("Content-Length", "83");
            conn.setRequestProperty("Content-Type", "text/plain");
            //发送POST请求必须设置如下两行
            conn.setDoInput(true);
            conn.setDoOutput(true);
            //获取conn对应的输出流
            outs = new OutputStreamWriter(conn.getOutputStream(), "utf-8");
            //发送请求参数
            String param = "";
            for(String s : Parameters){
                param += s+"\n";
            }
            //进行输出流的缓冲
            outs.write(param); // post的关键所在
            outs.flush();
            //通过BufferedReader输入流来读取Url的响应
            in=new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line;
            while((line=in.readLine())!= null){
                result += line;
            }
            System.out.println(result);
        } catch (Exception e) {
            System.out.println("发送post请求出现异常!"+e);
            e.printStackTrace();
        } finally{
            try{
                if(out != null){
                    out.close();
                }
                if(in!= null){
                    in.close();
                }
            }catch(IOException ex){
                ex.printStackTrace();
            }
        }
        return result;
    }

请求成功之后,返回如下数据:

{
   "remain":4999998,
   "success":2
}

 

B.Sitemap索引文件提交

 

注意,我这里用的是Sitemap索引文件而不是普通的xml,区别如下:https://ziyuan.baidu.com/college/courseinfo?id=267&page=2#04


百度Sitemap协议支持三种格式:文本格式、xml格式、Sitemap索引格式,可以根据自己情况来选择任意一种格式组织sitemap。具体格式说明及示例如下:
 

1.文本格式

在一个txt文本列明需要向百度提交的链接地址,将txt文本文件通过站长平台进行提交    
http://www.example.com/repaste/101562698_5230191316.html
http://www.example.com/repaste/101586283_5230215075.html
http://www.example.com/repaste/101639435_5230310576.html  

此文本文件需要遵循以下指南:
· 文本文件每行都必须有一个网址。网址中不能有换行。
· 不应包含网址列表以外的任何信息。
· 您必须书写完整的网址,包括 http。
· 每个文本文件最多可包含 50,000 个网址,并且应小于10MB(10,485,760字节)。如果网站所包含的网址超过 50,000 个,则可将列表分割成多个文本文件,然后分别添加每个文件。
· 文本文件需使用 UTF-8 编码或GBK编码。  

 

2.xml格式

单个xml数据格式如下:





    
        
        http://www.yoursite.com/yoursite.html
        
        2009-12-14
        
        daily
        
        0.8
        
    
    
        http://www.yoursite.com/yoursite2.html
        2010-05-01
        daily
        0.8
    


上述Sitemap向百度提交了一个url:http://www.yoursite.com/yoursite.html 
若有多条url,按照上述格式重复之间的片断,列明所有url地址,打包到一个xml文件,向站长平台进行提交。

 

3.Sitemap索引格式

 

如需提交大量sitemap文件,则可将其列在sitemap索引文件中,然后将该索引文件提交,您无需分别提交每个文件。





    
                
        http://example.com/ext/xmlsitemap/add/201201/index_20120106.xml
        
        2009-12-14
        
    
    

有多个Sitemap,按上述格式重复之间的片断,列明所有Sitemap地址,向站长平台进行提交。

 

注意:


第一,一个Sitemap文件包含的网址不得超过 5 万个,且文件大小不得超过 10 MB。如果您的Sitemap超过了这些限值,请将其拆分为几个小的Sitemap。这些限制条件有助于确保您的网络服务器不会因提供大文件而超载。

第二,一个站点支持提交的sitemap文件个数必须小于5万个,多于5万个后会不再处理,并显示“链接数超”的提示。    

第三,如果验证了网站的主域,那么Sitemap文件中可包含该网站主域下的所有网址。

 

在JAVA中创建xml格式的文件有以下几种方式:

1.手动拼接文件,组装格式,写入文件

2.通过jdom创建

3.通过sitemapgen4j

 

我这里提供2,3方式的代码,添加如下依赖:


	com.github.dfabulich
	sitemapgen4j
	1.1.1


	org.jdom
	jdom
	1.1.3

JDOM方式(代码中实现的是第2种方式提交,稍微改一下就可以第3种方式提交):

    public void createSiteMap(){
        String WEBSITE = "http://www.xxxx.com";
        Element urlset = new Element("urlset");
        Document document = new Document(urlset);
        List cList;
        if(cList == null || cList.size() < 1 ){
            return ;
        }
        int i=1;
        for (String category : cList) {
            System.out.println(category + "生成中..." + i);
            i++;
            //
            Element url = new Element("url");
            //
            Element loc = new Element("loc");
            loc.setText(WEBSITE + "/seo/" + category  +"/sitemap.xml");
            url.addContent(loc);
            urlset.addContent(url);
        }
        XMLOutputter XMLOut = new XMLOutputter();
        try {
            Format f = Format.getPrettyFormat();
            //default=UTF-8
            f.setEncoding("UTF-8");
            XMLOut.setFormat(f);
            String path = "D:\\tmp\\sitemap\\sitemap_index.xml";
            XMLOut.output(document, new FileOutputStream(path));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

sitemapgen4j方式

 

URL类

@XmlRootElement(name = "url")
public class Url {

    private String ioc;

    public Url() {
    }

    public Url(String ioc) {
        super();
        this.ioc = ioc;
    }

    @XmlElement(name = "ioc")
    public String getIoc() {
        return ioc;
    }

    public void setIoc(String ioc) {
        this.ioc = ioc;
    }

}

Sitemap类

@XmlRootElement(name = "sitemap")
public class Sitemap {

    private String ioc;

    public Sitemap() {
    }

    public Sitemap(String ioc) {
        super();
        this.ioc = ioc;
    }

    @XmlElement(name = "ioc")
    public String getIoc() {
        return ioc;
    }

    public void setIoc(String ioc) {
        this.ioc = ioc;
    }

}

工具类

import java.io.IOException;
import java.io.Writer;
import java.util.Iterator;

import javax.xml.bind.DataBindingException;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.PropertyException;

public class SiteMapUtils {

    protected final static String URLSET_START = "\n"
            + "\n";
    protected final static String URLSET_END = "\n";

	
    protected final static String SITEMAPINDEX_START = "\n"
            + "\n";

    protected final static String SITEMAPINDEX_STARTS = "\n"
            + "\n";

    protected final static String SITEMAPINDEX_END = "\n";

    public static void writeSitemapIndex(Writer writer, Iterator mappings) throws IOException {
        writeXml(writer, SITEMAPINDEX_STARTS, mappings, SITEMAPINDEX_END);
    }

    public static long writeUrlset(Writer writer, Iterator urls) throws IOException {
        return writeXml(writer, URLSET_START, urls, URLSET_END);
    }

    private static long writeXml(Writer writer, String start, Iterator it, String end) throws IOException {
        writer.write(start);
        long count = writeSubtree(writer, it);
        writer.write(end);
        return count;
    }

    public static long writeSubtree(Writer writer, Iterator it) throws IOException {
        long size = 0;
        Marshaller m;
        try {
            JAXBContext jc = JAXBContext.newInstance(Sitemap.class, Url.class);
            m = jc.createMarshaller();
            m.setProperty(Marshaller.JAXB_FRAGMENT, true);
            m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        } catch (PropertyException e) {
            throw new DataBindingException(e);
        } catch (JAXBException e) {
            throw new DataBindingException(e);
        }
        boolean first = true;
        while (it.hasNext()) {
            if (first) {
                first = false;
            } else {
                writer.write("\n");
            }
            try {
                m.marshal(it.next(), writer);
            } catch (JAXBException e) {
                throw new IOException(e);
            }
            size++;
        }
        return size;
    }

}

sitemap索引生成方法

    /**
     * 动态生成sitemap
     * 目录,web根目录,就是你的站点首页 index.html所在同级目录
     */
    public void createSiteMap(){
        try {
            long start = System.currentTimeMillis();
            String WEBSITE = "http://www.xxxx.com";
            String realPath = "D:\\tmp\\";
            List cList = findAllCategory();
            if(cList == null || cList.size() < 1 ){
                return ;
            }
            //存放子sitemap路径的list集合
            List siteMapList = Lists.newArrayList();
            for(Category category:cList){
                /** 查询每个分类下对应的文章 **/
                System.out.println("查询每个分类下对应的文章" + category.getId());
                List
aList = findArticleBy(category.getId()); if(aList != null && aList.size() > 0){ String path = realPath + category.getId(); //判断文件夹是否存在,不存在则创建 fileExists(path); WebSitemapGenerator sitemapGenerator = WebSitemapGenerator.builder(WEBSITE, new File(path)).gzip(false).build(); //遍历取出来的文章 for(Article article:aList){ //文章详情页的url地址 String url = StringUtils.join("http://www.xxxx.com/detail/",article.getId(),".html"); WebSitemapUrl sitemapUrl = new WebSitemapUrl.Options(url).lastMod(formatDate(article.getAddTime(), DATE_FORMAT)).priority(0.9).changeFreq(ChangeFreq.HOURLY).build(); sitemapGenerator.addUrl(sitemapUrl); } sitemapGenerator.write(); //主索引文件需要这个路径 siteMapList.add(WEBSITE + "/seo/" + category.getId() +"/sitemap.xml"); } } //其实分类 - list 页 url也应该存一个sitemap,看自己吧,如果也想告诉搜索引擎,我的list列表页也很重要,那么就做 /** 生成主索引文件 **/ if(siteMapList!=null && siteMapList.size()>0){ Collection s = new ArrayList(); for(String url:siteMapList){ s.add(new Sitemap(url)); } Writer wt = new PrintWriter(new File(realPath + "/sitemap.xml")); SiteMapUtils.writeSitemapIndex(wt, s.iterator()); wt.close(); } long end = System.currentTimeMillis(); System.out.println("生成Sitemap完毕, 共耗时:"+(end-start)); } catch (Exception e) { e.printStackTrace(); } }

这样就会在seo目录下创建一个sitemap.xml总的索引文件,链接到a/b/c啥啥分类目录,每个分类目录下有个sitemap.xml用来记录该分类下的所有链接。

 

你可能感兴趣的:(WEB开发)