如何让搜索引擎抓取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 相关文章推荐
第十四节--命名空间
Nov 16 PHP
PHP 输出简单动态WAP页面
Jun 09 PHP
php下正则来匹配dede模板标签的代码
Aug 21 PHP
php牛逼的面试题分享
Jan 18 PHP
解析数组非数字键名引号的必要性
Aug 09 PHP
50个PHP程序性能优化的方法
Jun 02 PHP
PHP+FFMPEG实现将视频自动转码成H264标准Mp4文件
Sep 24 PHP
PDO预处理语句PDOStatement对象使用总结
Nov 20 PHP
Yii入门教程之Yii安装及hello world
Nov 25 PHP
ThinkPHP静态缓存简单配置和使用方法详解
Mar 23 PHP
php实现产品加入购物车功能(1)
Jul 23 PHP
php与阿里云短信接口接入操作案例分析
May 27 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
解析php dirname()与__FILE__常量的应用
2013/06/24 PHP
PHP封装的一个支持HTML、JS、PHP重定向的多功能跳转函数
2014/06/19 PHP
PHP使用array_merge重新排列数组下标的方法
2015/07/22 PHP
php workerman定时任务的实现代码
2018/12/23 PHP
PHP simplexml_load_string()函数实例讲解
2019/02/03 PHP
laravel实现Auth认证,登录、注册后的页面回跳方法
2019/09/30 PHP
THINKPHP-Apache服务器中使用Alias虚拟目录URL重写 隐藏index.php
2021/03/09 PHP
document.getElementById的简写方式(获取id对象的简略写法)
2010/09/10 Javascript
多个表单中如何获得这个文件上传的网址实现js代码
2013/03/25 Javascript
简单实用jquery版三级联动select示例
2013/07/04 Javascript
js脚本实现数据去重
2014/11/27 Javascript
详解AngularJS Filter(过滤器)用法
2015/12/28 Javascript
html判断当前页面是否在iframe中的实例
2016/11/30 Javascript
JS封装通过className获取元素的函数示例
2016/12/20 Javascript
socket.io学习教程之基本应用(二)
2017/04/29 Javascript
vue router2.0二级路由的简单使用
2017/07/05 Javascript
jQuery 实时保存页面动态添加的数据的示例
2017/08/14 jQuery
vue中render函数的使用详解
2018/10/12 Javascript
express启用https使用小记
2019/05/21 Javascript
微信小程序点击保存图片到本机功能
2019/12/13 Javascript
微信小程序自定义扫码功能界面的实现代码
2020/07/02 Javascript
[57:53]DOTA2上海特级锦标赛主赛事日 - 2 败者组第二轮#3OG VS VP
2016/03/03 DOTA
Python中Class类用法实例分析
2015/11/12 Python
Python pymongo模块常用操作分析
2018/09/01 Python
浅析python 中大括号中括号小括号的区分
2019/07/29 Python
python pyinstaller打包exe报错的解决方法
2019/11/02 Python
Pytorch to(device)用法
2020/01/08 Python
详解python破解zip文件密码的方法
2020/01/13 Python
python实现提取str字符串/json中多级目录下的某个值
2020/02/27 Python
Python run()函数和start()函数的比较和差别介绍
2020/05/03 Python
在终端启动Python时报错的解决方案
2020/11/20 Python
Java的接口和C++的虚类的相同和不同处
2014/03/27 面试题
基层党员对照检查材料
2014/08/25 职场文书
Python机器学习之逻辑回归
2021/05/11 Python
logback 实现给变量指定默认值
2021/08/30 Java/Android
python分分钟绘制精美地图海报
2022/02/15 Python