公司使用angularJs(以下都是指ng1)框架做了互联网应用,之前没接触过seo,突然一天运营那边传来任务:要给网站做搜索引擎优化,需要研发支持。搜了下发现单页面应用做seo比较费劲,国内相关实践资料分享出来的也比较少,略懵,前后花了一番功夫总算完成了。在这里记录下来,做一个总结,也希望能够帮助在做类似工作的朋友少走一点弯路。还是建议需要seo的网站技术选型尽量不要使用angular react一类的单页面框架。如果你和我一样网站做完了发现需要seo,那么往下看吧。如果各位已有更优的方案欢迎拍砖交流。

  单页面应用seo的困难在哪里?

  做seo必须了解爬虫工作的基本原理。 搜索引擎能够搜到一个网页是因为对其做了索引,而在这之前需要爬虫抓取到网站页面存储为一个快照,快照的内容即页面的静态内容。一般来说,右键查看网页源代码看到的内容即爬虫所能抓取到的内容。爬虫拿到一个url后抓取其页面信息,查找页面中的a标签,拿到下一个url跳转地址,继续下一个页面抓取。seo的工作目的是增加搜索引擎对网站的索引量以及提升网页排名,传统的seo工作例如站内tdk的优化、网站url优化、外链增加都是为了达到这些目的。做到这些有一个共同的前提,就是网页内容能够被搜索引擎抓取到,而单页面应用seo的困难就卡在这里。

  如果你的应用是angularjs这类单页面应用开发的,右键查看源代码你会发现网站没有动态数据。很遗憾、搜索引擎来抓取的页面也会是这样。这主要是因为两点原因:

  路由、模板和ajax请求

   angular实现单页面的方案是利用了路由机制配合模板引擎。通过自定义模板,一个应用只有一个主页面,通过路由切换不同的状态,嵌套对应的模板引擎。而模板中的动态数据,都是通过ajax请求从后端拿到的。这从路由跳转到渲染出完整页面的过程,除了主页面基本的静态数据,其他的全靠js来完成。

  爬虫不执行js

   第一条明白之后看到这里也就很明显了。很遗憾,爬虫不执行js脚本,这个也不难理解,搜索引擎每天都有海量的页面要抓取,执行js会大大降低效率;另外搜索引擎执行js脚本也存在着巨大的安全隐患。

   搜索引擎拿到一个url后,获取,结束,仅仅拿到主页面中了了的几行静态信息。angular框架维护的路由、主页面,以及前端像后端发起的ajax请求等等js完成的工作,搜索引擎一概不会处理。

  url优化

  可抓取方案放到下面,先说说url优化。用过angularjs的都知道,ng的url是靠#来标识一个状态。含#类似符号的url对于seo是非常不友好的,而且据同事反应(本人没有验证),搜索引擎在访问url的时候并不会带着#后的内容去访问。总之,url优化是单页面应用seo绕不开的一个工作,而我们的目的,是把url优化成如同 www.xxx.com/111/222/333 目录结构的url,它是爬虫最喜欢的形态。

  如何去除ng框架url中的#,google和百度都能够搜到不少资料。如:http://blog.fens.me/angularjs-url/

  简单来说,去除#只需要在路由中配置$locationProvider.html5Mode(true); 开启html5模式,url会自动去除#以及.html后缀达到最优。但这时存在问题:f5刷新会404找不到页面,原因是f5会把url提交到后端获取资源,而html5模式优化后的url在后端并不存在这样一个资源,直接访问这个链接会连主页面都找不到,自然就会404。以上链接给出的方案是nodejs后端的方案,我们的方案是用springMVC后端,不过原理都是类似的:后端不认识这个链接,我们就把这个错误的连接重定向到原本带#的连接,对于后端来说就是一个正常的访问,而url中的#在浏览器端会再次被html5模式给去除。

  重定向的工作可以放在后端springMVC的过滤器中解决,也可以在容器中解决。我们的框架是后端用nginx做负载均衡,我将重定向放在nginx.conf中,对每个路由状态的url都做了对应的原始url重定向,问题解决。无论如何刷新、访问,页面都是简单舒适的目录结构url。

  两种可抓取解决方案

  url优化之后,继续往下看。说白了我们要做的就是单页面应用的可抓取方案,即:如何让搜索引擎能够获取到完整内容的页面信息。我调研了现有的一些解决方案,思路都是类似的。搜索引擎不执行js,我们改变不了,那么我们只有像照顾婴儿一样,自己将js执行,拿到模板以及动态数据渲染出一个完全静态的页面,交给爬虫。我调研过git上的两个方案,做一个分享,如果大家有更好的方案也欢迎分享。

  方案一、johnhuang-cn/AngularSEO

  https://github.com/johnhuang-cn/AngularSEO,这是一个java后端的解决方案。主要分为两块:服务端过滤器,本地爬虫。服务端过滤器有两个作用:一是为了拿到url,二是识别搜索引擎请求并重定向到本地快照;本地爬虫是为了渲染页面为本地快照。工作流程大致如下:

web.xml中配置上过滤器,第一次访问网站的时候过滤器抓取到url,交给本地爬虫。这个爬虫是一个拥有动态数据抓取能力的爬虫,主要利用了selenium+phantomjs框架,关于这两个框架可以自行google,其中phantomjs是一个webkit内核。它能够抓取动态数据的原因就在于它可以获取dom元素执行事件以及相关js。在获取到完整的页面信息后,它会将形如:http://abc.com/#/about的url对应静态存储到本地命名为http://abc.com/_23/about 的快照。也就是说,我们需要等待本地爬虫将每个url渲染出本地快照,然后搜索引擎爬虫来访问时,过滤器将请求重定向到对应的快照页面。过滤器如何识别爬虫呢?是通过http包头中的userAgent,每个搜索引擎拥有自己的userAgent,在过滤器内配置上即可。

  优点:这个方案有几个优点。1、部署相对简单,对于java应用来说,配置相对方便简单。2、搜索引擎访问效率较快,由于快照已经被保存好了,搜索引擎来抓取后直接会返回静态页面。

  弊端:这个方案同样存在几个弊端。1、本地爬虫抓取速度慢,对于我们拥有海量动态数据的如资讯模块,保存快照是个耗时的工作。2、实时性,框架通过配置本地爬取频率来更新快照,意味着搜索引擎抓取页面的实时性受限于更新频率。3、稳定性,不知道现在是否还存在这些问题,可能由于当时该框架还不很成熟,我在试用中,本地爬虫的激活不够稳定,另外phantomjs进程出现过无法退出的现象,导致后台开启大量phantomjs内存耗尽。4、分布式部署问题,我们利用nginx负载均衡做了后端集群,搜索引擎来了之后按规则分配到不同后端,导致使用此框架需要在每个后端部署,引来一系列不便和问题。

由于以上弊端,此方案最终被我放弃了。

方案二、prerender.io 

  该方案是我调研过程中找到的相对成熟的解决方案,较为完美的解决了我的需求。原理图如下,可参考:http://www.cnblogs.com/whitewolf/p/3464555.html

  prerender.io也分为两块,客户端以及服务端prerender服务,客户端的工作是识别搜索引擎请求并做重定向(和方案一类似),除了userAgent它还会通过escaped_fragment做搜索引擎识别,这是谷歌的一套可抓取方案,详情可见:Google's ajax crawling protocol。如果你的站点主要是做国内浏览器的优化基本可以忽略,单使用userAgent足够了。prerender服务端负责接收客户端重定向过来的请求,拿到请求后再次去向web后端做请求,同样,prerender后端集成了phantomjs,来执行js获取动态数据。拿到完整的页面数据之后,prerender后端将完整页面返回给搜索引擎。

  prerender的客户端现在拥有很多种技术实现,基本可以满足各类技术方案。服务端拥有两种选择:1、使用官方提供的prerender.io云服务 2、搭建自己的prerender后端服务。官网上的介绍推荐使用云服务,不过官网需要FQ,而且使用别人的服务稳定性总是令人担忧的,我选择了自己部署prerender服务。它其实就是个单独在跑的nodejs进程,使用forever指令跑起来之后还是很稳定的。

  优点:1、高实时性,通过上面分析可以明白prerender服务是实时拿到搜索引擎请求去做页面渲染的,这意味着一次部署后如果站点没有大的改动便没有了后续工作,搜索引擎得到的每一次返回内容和用户访问的一样都是最新的数据。2、分布式部署,prerender服务是完全和web应用分离的一个进程,不管后端有多少集群都和部署互不影响。3、稳定性,框架已经相对成熟,缓存机制、黑白名单体验起来都很不错。prerender服务用forever守护进程跑起来之后基本上没有遇到不稳定的问题。

  缺点:1、搜索引擎抓取效率,页面是实时渲染的,搜索引擎抓取起来自然会慢一些,不过这个我们并不很关心。

比较两个方案我自然选择了prerender的方案,部署实践的过程也遇到过一系列问题,如果需要我后续会写prerender部署实践文章。

  总结

总的来说,单页面应用可抓取的最大问题就在于搜索引擎不执行js,解决方案无非就是我们自己做动态数据渲染然后喂给爬虫。确定了这些,即使自己去完成这样一个框架也不是一件困难的事了。

  

基于angularJs的单页面应用seo优化及可抓取方案原理分析的更多相关文章

  1. 基于AngularJs的单页面程序

    基于AngularJs的单页面程序 在Abpzero的后台管理系统是一个AngularJs的单页面程序.当你登陆后,系统会跳转到"ApplicationController",然后 ...

  2. 处理 Vue 单页面应用 SEO 的另一种思路

    vue-meta-info 官方地址: monkeyWangs/vue-meta-info (设置vue 单页面meta info信息,如果需要单页面SEO,可以和 prerender-spa-plu ...

  3. AngularJs(SPA)单页面SEO以及百度统计应用(上)

    只有两种人最具有吸引力,一种是无所不知的人,一种是一无所知的人 问:学生问追一个女孩总是追不上怎么办?回答:女孩不是追来的,是吸引来的,你追的过程是吸引女孩的过程,如果女孩没有看上你,再追都是没有用的 ...

  4. Vue 单页面应用 SEO SPA single page application advantages and disadvantages

    处理 Vue 单页面应用 SEO 的另一种思路 - muwoo - 博客园 https://www.cnblogs.com/tiedaweishao/p/7493971.html SPA网站SEO完美 ...

  5. HTML5 VUE单页应用 SEO 优化之 预渲染(prerender-spa-plugin)

    前言:当前 SPA 架构流行的趋势如日中天,前后端分离的业务模式已经成为互联网开发的主流方式,但是 单页面 应用始终存在一个痛点,那就是 SEO, 对于那些需要推广,希望能在百度搜索时排名靠前的网站而 ...

  6. vue单页面处理SEO问题

    设置vue 单页面meta info信息 vue-meta-info,(https://github.com/muwoo/vue-meta-info)如果需要单页面SEO,可以和 prerender- ...

  7. vue单页面应用项目优化总结(转载)

    转载自:https://blog.csdn.net/qq_42221334/article/details/81907901这是之前在公司oa项目优化时罗列的优化点,基本都已经完成,当时花了点心思整理 ...

  8. 基于Vue的单页面应用的Markdown渲染

    之前渲染 Markdown 的时候, 笔者使用的是 mavonEditor 的预览模式, 使用起来比较爽, 只需要引入组件即可, 但是在最近的开发中, 遇到了困难. 主要问题在于作为单页面应用, 站内 ...

  9. AngularJs(SPA)单页面SEO以及百度统计应用(下)

    苍苍之天不得久视,堂堂之地不得久履 当你小心翼翼的开启服务端渲染的同时,一个问题不得不注意,使用内存模式去保存渲染过的页面,这样服务断掉重启后,缓存也没有了,所以这里我们使用mongdodb进行本地化 ...

随机推荐

  1. Centos 7 安装mysql后出现 ERROR 2002 (HY000)解决方案

    Centos 7 安装mysql后出现 ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib ...

  2. bzoj4825 [Hnoi2017]单旋

    Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的必 ...

  3. Windows7下安装IIS

    1.点击开始→控制面板,然后再点击程序,勿点击卸载程序,否则到不了目标系统界面. 2.然后在程序和功能下面,点击打开和关闭windows功能. 3.进入Windows功能窗口,然后看到internet ...

  4. JS面向对象,创建,继承

    很开心,最近收获了很多知识,而且发现很多东西,以前理解的都是错的,或者是肤浅的,还以为自己真的就get到了精髓,也很抱歉会影响一些人往错误的道路上走,不过这也告诉了我们,看任何一篇文章都不能盲目的去相 ...

  5. web开发中,post与get的区别

    区别: 1.Get是从服务器上获取数据,Post是向服务器传送数据. 2.Get是把参数数据队列加到提交表单的Action属性所指的URL中,值和表单内各个字段一一对应,在URL中可以看到.Post是 ...

  6. 使用JavaEE的ServerAuthModule模块和web.xml进行相应配置,实现对用户的权限控制

    ServerAuthModule这里不细说,可以自行百度. 重点在注释: <!-- 声明用于安全约束的角色 --> <security-role> <role-name& ...

  7. 亲测可用!!!golang如何在idea中保存时自动进行代码格式化

    亲测可用,golang在idea中的代码自动格式化 1.ctrl+alt+s打开设置界面,选择[Plugins] -> [Install JetBrains plugin...] -> 搜 ...

  8. SDN学习之OpenFlow协议分析

    学习SDN相关的学习也已经有快半年了,期间从一无所知到懵懵懂懂,再到现在的有所熟悉,经历了许多,也走了不少弯路,其中,最为忌讳的便是,我在学习过程中,尚未搞明白OpenFlow协议的情况下,便开始对S ...

  9. coding.net及git的使用方式

    一般部分测试的公司里可能会用到代码管理工具,这里可能不得不推荐coding.net和git这个工具,类似于svn,不过用命令行的情况多点 这里简单介绍下 1.建立coding.net 首先新建一个co ...

  10. Android分享功能实现

    通过系统分享组件实现分享功能 Intent.createChooser() 方法用来弹出系统分享列表. createChooser(Intent target, CharSequence title, ...