如何让搜索引擎抓取AJAX内容解决方案


Posted in PHP onAugust 25, 2014

越来越多的网站,开始采用"单页面结构"(Single-page application)。

整个网站只有一张网页,采用Ajax技术,根据用户的输入,加载不同的内容。

如何让搜索引擎抓取AJAX内容解决方案

这种做法的好处是用户体验好、节省流量,缺点是AJAX内容无法被搜索引擎抓取。举例来说,你有一个网站。

http://example.com

用户通过井号结构的URL,看到不同的内容。

http://example.com#1
http://example.com#2
http://example.com#3

但是,搜索引擎只抓取example.com,不会理会井号,因此也就无法索引内容。

为了解决这个问题,Google提出了"井号+感叹号"的结构。

http://example.com#!1

当Google发现上面这样的URL,就自动抓取另一个网址:

http://example.com/?_escaped_fragment_=1

只要你把AJAX内容放在这个网址,Google就会收录。但是问题是,"井号+感叹号"非常难看且烦琐。Twitter曾经采用这种结构,它把

http://twitter.com/ruanyf

改成

http://twitter.com/#!/ruanyf

结果用户抱怨连连,只用了半年就废除了。

那么,有没有什么方法,可以在保持比较直观的URL的同时,还让搜索引擎能够抓取AJAX内容?

我一直以为没有办法做到,直到前两天看到了Discourse创始人之一的Robin Ward的解决方法,不禁拍案叫绝。

如何让搜索引擎抓取AJAX内容解决方案

Discourse是一个论坛程序,严重依赖Ajax,但是又必须让Google收录内容。它的解决方法就是放弃井号结构,采用 History API。

所谓 History API,指的是不刷新页面的情况下,改变浏览器地址栏显示的URL(准确说,是改变网页的当前状态)。这里有一个例子,你点击上方的按钮,开始播放音乐。然后,再点击下面的链接,看看发生了什么事?

如何让搜索引擎抓取AJAX内容解决方案

地址栏的URL变了,但是音乐播放没有中断!

History API 的详细介绍,超出这篇文章的范围。这里只简单说,它的作用就是在浏览器的History对象中,添加一条记录。

window.history.pushState(state object, title, url);

上面这行命令,可以让地址栏出现新的URL。History对象的pushState方法接受三个参数,新的URL就是第三个参数,前两个参数都可以是null。

window.history.pushState(null, null, newURL);

目前,各大浏览器都支持这个方法:Chrome(26.0+),Firefox(20.0+),IE(10.0+),Safari(5.1+),Opera(12.1+)。

下面就是Robin Ward的方法。

首先,用History API替代井号结构,让每个井号都变成正常路径的URL,这样搜索引擎就会抓取每一个网页。

example.com/1
example.com/2
example.com/3

然后,定义一个JavaScript函数,处理Ajax部分,根据网址抓取内容(假定使用jQuery)。

function anchorClick(link) {

var linkSplit = link.split('/').pop();


$.get('api/' + linkSplit, function(data) {



$('#content').html(data);


});

}

再定义鼠标的click事件。

$('#container').on('click', 'a', function(e) {


window.history.pushState(null, null, $(this).attr('href'));


anchorClick($(this).attr('href'));


e.preventDefault();

});

还要考虑到用户点击浏览器的"前进 / 后退"按钮。这时会触发History对象的popstate事件。

window.addEventListener('popstate', function(e) {     


anchorClick(location.pathname);  
 
});

定义完上面三段代码,就能在不刷新页面的情况下,显示正常路径URL和AJAX内容。

最后,设置服务器端。

因为不使用井号结构,每个URL都是一个不同的请求。所以,要求服务器端对所有这些请求,都返回如下结构的网页,防止出现404错误。

<html>


<body>



<section id='container'></section>



<noscript>




... ...
 


</noscript>


</body>

</html>

仔细看上面这段代码,你会发现有一个noscript标签,这就是奥妙所在。

我们把所有要让搜索引擎收录的内容,都放在noscript标签之中。这样的话,用户依然可以执行AJAX操作,不用刷新页面,但是搜索引擎会收录每个网页的主要内容!

PHP 相关文章推荐
PHP生成静态页面详解
Dec 05 PHP
PHP产生随机字符串函数
Dec 06 PHP
php 正则匹配函数体
Aug 25 PHP
PHP的变量总结 新手推荐
Apr 18 PHP
ThinkPHP3.1新特性之对分组支持的改进与完善概述
Jun 19 PHP
PHP封装的HttpClient类用法实例
Jun 17 PHP
WordPress中获取指定分类及其子分类下的文章数目
Dec 31 PHP
thinkPHP3.x常量整理(预定义常量/路径常量/系统常量)
May 20 PHP
PHP实现加密文本文件并限制特定页面的存取的效果
Oct 21 PHP
解析PHP之提取多维数组指定列的方法
Jan 03 PHP
php从数据库读取数据,并以json格式返回数据的方法
Aug 21 PHP
PHP获取对象属性的三种方法实例分析
Jan 03 PHP
使用php方法curl抓取AJAX异步内容思路分析及代码分享
Aug 25 #PHP
简单分析ucenter 会员同步登录通信原理
Aug 25 #PHP
ThinkPHP调用common/common.php函数提示错误function undefined的解决方法
Aug 25 #PHP
ThinkPHP查询返回简单字段数组的方法
Aug 25 #PHP
php防止伪造数据从地址栏URL提交的方法
Aug 24 #PHP
php批量删除数据库下指定前缀的表以prefix_为例
Aug 24 #PHP
一个图片地址分解程序(用于PHP小偷程序)
Aug 23 #PHP
You might like
五款常用mysql slow log分析工具的比较分析
2011/05/22 PHP
php数据库配置文件一般做法分享
2012/07/07 PHP
Codeigniter中禁止A Database Error Occurred错误提示的方法
2014/06/12 PHP
CI框架中zip类应用示例
2014/06/17 PHP
Yii2.0高级框架数据库增删改查的一些操作
2015/11/16 PHP
jquery 指南/入门基础
2007/11/30 Javascript
javascript setAttribute, getAttribute 在不同浏览器上的不同表现
2010/08/05 Javascript
JS中的public和private对象,即static修饰符
2012/01/18 Javascript
如何使用Javascript正则表达式来格式化XML内容
2013/07/04 Javascript
jquery插件lazyload.js延迟加载图片的使用方法
2014/02/19 Javascript
JS实现同时搜索百度和必应的方法
2015/01/27 Javascript
jquery ajax 如何向jsp提交表单数据
2015/08/23 Javascript
js实现横向伸展开的二级导航菜单代码
2015/08/28 Javascript
jquery实现加载进度条提示效果
2015/11/23 Javascript
js实现兼容IE、Firefox的图片缩放代码
2015/12/08 Javascript
前端js实现文件的断点续传 后端PHP文件接收
2016/10/14 Javascript
Angularjs中ng-repeat-start与ng-repeat-end的用法实例介绍
2016/12/31 Javascript
详解如何使用Vue2做服务端渲染
2017/03/29 Javascript
详解JS中统计函数执行次数与执行时间
2018/09/04 Javascript
Vue组件实现触底判断
2019/06/26 Javascript
Vue中keep-alive的两种应用方式
2020/07/15 Javascript
详解Vue.js3.0 组件是如何渲染为DOM的
2020/11/10 Javascript
Python中的测试模块unittest和doctest的使用教程
2015/04/14 Python
在Django同1个页面中的多表单处理详解
2017/01/25 Python
Python批量更改文件名的实现方法
2017/10/29 Python
python中is与双等于号“==”的区别示例详解
2017/11/21 Python
python config文件的读写操作示例
2019/09/27 Python
tensorflow 实现数据类型转换
2020/02/17 Python
解决Django提交表单报错:CSRF token missing or incorrect的问题
2020/03/13 Python
可自定义箭头样式的CSS3气泡提示框
2016/03/16 HTML / CSS
TALLY WEiJL法国网上商店:服装、时装及配饰
2019/08/31 全球购物
管理科学大学生求职信
2013/11/13 职场文书
教师党员思想汇报
2014/01/06 职场文书
岗位说明书怎么写
2014/07/30 职场文书
幼儿教师三分钟演讲稿
2019/06/21 职场文书
Python下载商品数据并连接数据库且保存数据
2022/03/31 Python