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

一、前言

 

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

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

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

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

<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
		http://www.sitemaps.org/schemas/sitemap/0.9/siteindex.xsd">

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

 

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

 

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

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

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

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

 

先说下什么是sitemap?

 

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

 

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

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

2.手动提交


 

二、操作

 

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数据格式如下:

<?xml version="1.0" encoding="utf-8"?>
<!-- XML文件需以utf-8编码-->
<urlset>
<!--必填标签-->
    <url>
        <!--必填标签,这是具体某一个链接的定义入口,每一条数据都要用<url>和</url>包含在里面,这是必须的 -->
        <loc>http://www.yoursite.com/yoursite.html</loc>
        <!--必填,URL链接地址,长度不得超过256字节-->
        <lastmod>2009-12-14</lastmod>
        <!--可以不提交该标签,用来指定该链接的最后更新时间-->
        <changefreq>daily</changefreq>
        <!--可以不提交该标签,用这个标签告诉此链接可能会出现的更新频率 -->
        <priority>0.8</priority>
        <!--可以不提交该标签,用来指定此链接相对于其他链接的优先权比值,此值定于0.0-1.0之间-->
    </url>
    <url>
        <loc>http://www.yoursite.com/yoursite2.html</loc>
        <lastmod>2010-05-01</lastmod>
        <changefreq>daily</changefreq>
        <priority>0.8</priority>
    </url>
</urlset>


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

 

3.Sitemap索引格式

 

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

<?xml version="1.0" encoding="utf-8"?>
<!-- XML文件需以utf-8编码-->
<sitemapindex>
<!--必填,以 <sitemapindex> 开始标记作为开始,以 </sitemapindex> 结束标记作为结束-->
    <sitemap>
        <!--必填,以<sitemap>标签提交一个子sitemap文件-->        
        <loc>http://example.com/ext/xmlsitemap/add/201201/index_20120106.xml</loc>
        <!--必填,识别sitemap的位置-->
        <lastmod>2009-12-14</lastmod>
        <!--选填,识别相对sitemap文件的修改时间-->
    </sitemap>
    <!--必填,标签闭合-->
</sitemapindex>
<!--必填,标签闭合-->

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

 

注意:


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

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

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

 

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

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

2.通过jdom创建

3.通过sitemapgen4j

 

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

<dependency>
	<groupId>com.github.dfabulich</groupId>
	<artifactId>sitemapgen4j</artifactId>
	<version>1.1.1</version>
</dependency>
<dependency>
	<groupId>org.jdom</groupId>
	<artifactId>jdom</artifactId>
	<version>1.1.3</version>
</dependency>

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

    public void createSiteMap(){
        String WEBSITE = "http://www.xxxx.com";
        Element urlset = new Element("urlset");
        Document document = new Document(urlset);
        List<String> cList;
        if(cList == null || cList.size() < 1 ){
            return ;
        }
        int i=1;
        for (String category : cList) {
            System.out.println(category + "生成中..." + i);
            i++;
            //<!--必填标签,这是具体某一个链接的定义入口,每一条数据都要用<url>和</url>包含在里面,这是必须的 -->
            Element url = new Element("url");
            //<!--必填,URL链接地址,长度不得超过256字节-->
            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 = "<?xml version='1.0' encoding='UTF-8'?>\n"
            + "<urlset xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
            + "         xsi:schemaLocation=\"http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd\"\n"
            + "         xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n";
    protected final static String URLSET_END = "\n</urlset>";

	
    protected final static String SITEMAPINDEX_START = "<?xml version='1.0' encoding='UTF-8'?>\n"
            + "<sitemapindex xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
            + "         xsi:schemaLocation=\"http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/siteindex.xsd\"\n"
            + "         xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n";

    protected final static String SITEMAPINDEX_STARTS = "<?xml version='1.0' encoding='UTF-8'?>\n"
            + "<sitemapindex>\n";

    protected final static String SITEMAPINDEX_END = "\n</sitemapindex>";

    public static void writeSitemapIndex(Writer writer, Iterator<? extends Sitemap> mappings) throws IOException {
        writeXml(writer, SITEMAPINDEX_STARTS, mappings, SITEMAPINDEX_END);
    }

    public static long writeUrlset(Writer writer, Iterator<Url> 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<Category> cList = findAllCategory();
            if(cList == null || cList.size() < 1 ){
                return ;
            }
            //存放子sitemap路径的list集合
            List<String> siteMapList = Lists.newArrayList();
            for(Category category:cList){
                /** 查询每个分类下对应的文章 **/
                System.out.println("查询每个分类下对应的文章" + category.getId());
                List<Article> 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<Sitemap> 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用来记录该分类下的所有链接。

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值