关于html5:搜索引擎如何处理AngularJS应用程序?

How do search engines deal with AngularJS applications?

我发现AngularJS应用程序在搜索引擎和SEO方面存在两个问题:

1)定制标签会发生什么情况?搜索引擎会忽略这些标签中的全部内容吗?也就是说,假设我有

1
2
3
<custom>
  Hey, this title is important
</custom>

即使在自定义标签中,是否会被索引?

2)是否有办法避免索引字面绑定的搜索引擎?即

1
{{title}}

我知道我可以做一些像

1
<h2 ng-bind="title">

但如果我真的想让爬虫"看到"标题呢?服务器端呈现是唯一的解决方案吗?


使用PushState和预组合

目前(2015年)的方法是使用javascript pushstate方法。好的。

PushState在不重新加载页面的情况下更改顶部浏览器栏中的URL。假设您有一个包含选项卡的页面。选项卡隐藏和显示内容,并动态插入内容,可以使用Ajax,也可以简单地设置display:none和display:block来隐藏和显示正确的选项卡内容。好的。

单击选项卡后,使用pushstate更新地址栏中的URL。呈现页面时,使用地址栏中的值确定要显示的选项卡。角度布线将自动为您完成此操作。好的。预构图

有两种方法可以点击PushState单页应用程序(SPA)好的。

  • 通过pushstate,用户单击pushstate链接,内容半开半入。
  • 直接点击URL。
  • 网站的初始点击将涉及直接点击URL。当pushstate更新url时,随后的点击将只是内容中的ajax。好的。

    爬虫从一个页面获取链接,然后将它们添加到一个队列中以供以后处理。这意味着对于爬虫来说,服务器上的每一次点击都是直接点击,它们不会通过pushstate导航。好的。

    预组合将初始负载捆绑到服务器的第一个响应中,可能作为JSON对象。这允许搜索引擎在不执行Ajax调用的情况下呈现页面。好的。

    有证据表明谷歌可能不会执行Ajax请求。更多信息:好的。

    https://web.archive.org/web/20160318211223/http://www.analog-ni.co/precomposing-a-spa-may-become-the-holy-grail-to-seo好的。搜索引擎可以读取和执行javascript

    谷歌已经能够解析javascript一段时间了,这就是为什么他们最初开发了Chrome,作为谷歌蜘蛛的全功能无头浏览器。如果链接具有有效的href属性,则可以索引新的URL。没什么可做的。好的。

    如果另外单击一个链接会触发pushstate调用,那么用户可以通过pushstate导航该站点。好的。搜索引擎对PushState URL的支持

    PushState目前由Google和Bing支持。好的。谷歌

    以下是Matt Cutts对Paul Irish关于搜索引擎优化的PushState问题的回应:好的。

    网址:http://youtu.be/yiaf9vdvrpw好的。

    下面是Google宣布对Spider提供完全的javascript支持:好的。

    http://googlewebmastercentral.blogspot.de/2014/05/understanding-web-pages-better.html好的。

    结果是,谷歌支持pushstate,并将为pushstate URL编制索引。好的。

    另请参见Google网站管理员工具的"作为GoogleBot获取"。您将看到您的javascript(包括angular)被执行。好的。冰

    以下是Bing于2013年3月发布的支持PushState网址的公告:好的。

    http:/ / / / blogs.bing.com站长2013/03/21/搜索引擎优化的最佳实践为Ajax URL /

    不要使用hashbangs #!

    hashbang URL是在《丑女stopgap开发者需要提供一个预之间的版本的网站在一个特殊的位置。他们安静的工作,但你不需要使用他们。

    hashbang网址看起来像这样:

    domain.com/#!path/to/resource

    这将是这样的:一个配对的meta标签

    谷歌希望他们在这逆境指数形式而不是静态的,但想拉A版本的网站从_ escaped _和指数是_ URL片段。

    pushstate看起来像任何普通的URL网址:

    domain.com/path/to/resource

    的差异是他们为你处理被拦截的角的变化对document.location JavaScript处理它。

    如果你想使用pushstate网址(你可能做了一切)把旧URL的哈希标签和简单的风格和时尚的配置启用HTML5块。

    测试你的网站

    现在,谷歌网站管理员工具中包含的工具,这将使你一个fetch a网址为谷歌,谷歌renders JavaScript和渲染它。

    http:/ / / / / Google站长工具Googlebot抓取

    生成的URL pushstate角

    生成的URL到房角,而不是一#字头,集时尚locationprovider HTML5的元对象。

    1
    $locationProvider.html5Mode(true);

    服务器端

    因为你使用的是实际的URL,你将需要确保相同的模板(加上一些内容,那么你的预shipped)在所有有效的服务器的URL。你这样做想有所不同,取决于您的服务器架构。

    网站地图

    您的应用程序可以使用常见的导航形式,例如悬停或滚动。确保你能在谷歌是一个可能的驱动程序,建议创建一个站点地图,一个简单的应用程序的URL清单,所有的对。你可以在默认位置(桩号本网站或/ sitemap.xml),或使用谷歌网站管理员工具,告诉它。

    这是一个很好的主意,无论如何有一个网站地图。

    浏览器支持

    pushstate ie10工场。在旧的浏览器会自动的情况下,角回的URL散列风格

    a演示页

    下面的内容是使用一个precomposition之间pushstate URL:

    http://html5.gingerhost.com /伦敦

    AS可以验证,在本环节内容的索引,和一个appearing在谷歌。

    301状态代码404头和服务

    因为我打你的搜索引擎服务器为每一个请求,你可以从你的头到服务器状态代码和谷歌期望看到他们。

    好的。


    2014年5月更新

    现在,谷歌搜索,你可以使用JavaScript的executes谷歌网站管理员工具来更好的理解你是如何rendered谷歌的网站。

    原始的答案如果你想优化你的应用程序中,有一个不幸的是搜索引擎服务的方式在以前的版本的rendered爬虫。你可以阅读更多关于谷歌的AJAX和JavaScript重建议网站在这里。

    如果这是一个选择,我建议阅读这篇关于SEO的角度是如何与服务器端绘制。

    我不知道什么时候它不接触的履带式的自定义标签。


    让我们确定一下AngularJS和SEO

    Google、Yahoo、Bing和其他搜索引擎使用传统的爬虫程序以传统方式对网络进行爬行。他们运行机器人在网页上爬行HTML,收集沿途的信息。他们保留有趣的单词,并寻找其他网页的链接(这些链接,它们的数量和它们与SEO一起使用的数量)。

    那么,为什么搜索引擎不处理javascript站点呢?

    答案与这样一个事实有关:搜索引擎机器人通过无头浏览器工作,而且他们通常没有JavaScript呈现引擎来呈现页面的JavaScript。这适用于大多数页面,因为大多数静态页面不关心JavaScript呈现其页面,因为它们的内容已经可用。

    对此可以做些什么?

    幸运的是,大型站点的爬虫程序已经开始实现一种机制,允许我们让我们的javascript站点可以爬虫,但它要求我们对我们的站点进行更改。

    如果我们把我们的hashPrefix改为#!,而不是简单的#,那么现代搜索引擎将改变使用_escaped_fragment_而不是#!的请求。(使用HTML5模式,即我们有没有哈希前缀的链接,我们可以通过查看后端中的User Agent头来实现这一功能)。

    也就是说,不是来自普通浏览器的请求,而是如下所示:

    http://www.ng-newsletter.com/#!/signup/page

    搜索引擎将使用以下内容搜索页面:

    http://www.ng-newsletter.com/?_escaped_fragment_=/signup/page

    我们可以使用来自ngRoute的内置方法设置角度应用程序的哈希前缀:

    1
    2
    3
    4
    angular.module('myApp', [])
    .config(['$location', function($location) {
      $location.hashPrefix('!');
    }]);

    而且,如果我们使用html5Mode,我们将需要使用meta标记来实现这一点:

    1
    <meta name="fragment" content="!">

    提醒:我们可以通过$location服务设置html5Mode()

    1
    2
    3
    4
    5
    angular.module('myApp', [])
    .config(['$location',
    function($location) {
      $location.html5Mode(true);
    }]);

    处理搜索引擎

    我们有很多机会来决定如何处理将内容作为静态HTML实际交付给搜索引擎。我们可以自己托管一个后端,我们可以使用一个服务为我们托管一个后端,我们可以使用代理来交付内容,等等。让我们来看几个选项:

    自托管

    我们可以编写一个服务来处理使用无头浏览器(如phantomjs或zombiejs)对自己的站点进行爬行的问题,使用呈现的数据获取页面快照并将其存储为HTML。每当我们在搜索请求中看到查询字符串?_escaped_fragment_时,我们就可以通过JS传递我们从页面中获取的静态HTML快照,而不是预先呈现的页面。这就要求我们有一个后端,用中间的条件逻辑来传递页面。我们可以使用prerender.io的后端作为自己运行的起点。当然,我们仍然需要处理代理和代码片段处理,但这是一个好的开始。

    提供有偿服务

    让内容进入搜索引擎的最简单和最快的方法是使用服务brombone、seo.js、seo4ajax和prerender.io,这些都是很好的例子,它们将为您托管上述内容呈现。在我们不想处理运行服务器/代理的情况下,这是一个很好的选择。而且,它通常非常快。

    关于Angular和SEO的更多信息,我们在http://www.ng-newsletter.com/posts/serior-angular-seo.html上写了一个关于它的广泛教程,我们在我们的Ng书《AngularJS全书》中更详细地介绍了它。在ng-book.com上查看。


    你真的应该检查网络教程SEO友好的网站建立一个网上angularjs年月的博客。合上你的所有步骤通角的轮廓在线文档。http:/ / / / / angularjs-and-seo.html 2012年11 www.yearofmoo.com

    使用这种技术的搜索引擎的位置,而不是HTML的扩展的自定义标签。


    这已经发生了巨大的变化。

    http://searchengineland.com/bing-offers-recommendions-for-seo-friendly-ajax-recommends-html5-pushstate-152946

    如果使用:$locationProvider.html5模式(真);你被设定了。

    不再呈现页面。


    事情已经改变了,因为这个问题是一位真正的问题。现在有选项让您angularjs谷歌索引的网站。我发现在easiest选项是使用http://prerender.io免费服务,将生成的页面,你crwalable和服务的搜索引擎。它支持几乎所有的Web服务器端的在线平台。最近我已经开始使用他们的支持是很优秀的。

    我没有任何与他们的d'affiliation,这是来自快乐的用户。


    你自己的角的网站内容对搜索引擎┊简体docs.angularjs.org:http:///?_ escaped _片段_ = /导师/步_ 09

    在你的应用程序是一个耗时的角度说Node.js API驱动/ JSON表示,/api/path/to/resource样。也许你可以重定向到任何要求与?_escaped_fragment_/api/path/to/resource.html投降的谈判,和使用的HTML模板到一个内容的内容,而不是将JSON数据。

    唯一的事情是,你将需要匹配的角线1与1:你的REST的API。

    编辑:我实现这个潜能有泥泞的REST API到真的让你和我不建议做它在非常简单的情况下,它可能是使用天然的契合。

    相反,你可以使用一个完全不同的一套路线和你友好的机器人控制器的内容。然后你和你所有的duplicating angularjs路线节点控制器中的表达。

    我已经落户与无头的快照生成的浏览器,虽然我觉得这是一个小的小于理想。


    这里有一个很好的做法:

    http://scotch.io/tutorials/javascript/angularjs-seo-with-prerender-io?_转义的片段标记


    到目前为止,谷歌已经改变了他们的Ajax爬行计划。

    Times have changed. Today, as long as you're not blocking Googlebot from crawling your JavaScript or CSS files, we are generally able to render and understand your web pages like modern browsers.

    tl;dr:[google]不再推荐2009年提出的ajax爬行方案[google]。


    谷歌的爬行式Ajax规范,在这里的其他答案中引用,基本上就是答案。

    如果你对其他搜索引擎和社交机器人如何处理同样的问题感兴趣,我在这里写下了最新进展:http://blog.ajaxsnapshots.com/2013/11/googles-crawlable-ajax-specification.html

    我在一家https://ajaxsnapshots.com公司工作,这家公司将可爬行的Ajax规范作为一项服务来实现——该报告中的信息基于我们日志中的观察结果。


    我找到了一个优雅的解决方案,可以覆盖你的大部分基地。我最初是在这里写的,在这里回答了另一个类似的StackOverflow问题,它引用了这个问题。

    仅供参考,此解决方案还包括硬编码的回退标签,以防爬虫程序无法获取javascript。我没有明确地概述它,但值得一提的是,您应该激活HTML5模式以获得适当的URL支持。

    还要注意:这些不是完整的文件,只是相关文件的重要部分。如果需要帮助,可以在其他地方找到指令、服务等的样板文件。不管怎样,这是…

    App.JS

    这是您为每个路由(标题、描述等)提供自定义元数据的地方。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    $routeProvider
       .when('/', {
           templateUrl: 'views/homepage.html',
           controller: 'HomepageCtrl',
           metadata: {
               title: 'The Base Page Title',
               description: 'The Base Page Description' }
       })
       .when('/about', {
           templateUrl: 'views/about.html',
           controller: 'AboutCtrl',
           metadata: {
               title: 'The About Page Title',
               description: 'The About Page Description' }
       })

    metadata-service.js(服务)

    设置自定义元数据选项或将默认值用作回退。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    var self = this;

    // Set custom options or use provided fallback (default) options
    self.loadMetadata = function(metadata) {
      self.title = document.title = metadata.title || 'Fallback Title';
      self.description = metadata.description || 'Fallback Description';
      self.url = metadata.url || $location.absUrl();
      self.image = metadata.image || 'fallbackimage.jpg';
      self.ogpType = metadata.ogpType || 'website';
      self.twitterCard = metadata.twitterCard || 'summary_large_image';
      self.twitterSite = metadata.twitterSite || '@fallback_handle';
    };

    // Route change handler, sets the route's defined metadata
    $rootScope.$on('$routeChangeSuccess', function (event, newRoute) {
      self.loadMetadata(newRoute.metadata);
    });

    metaproperty.js(指令)

    Packages the metadata service results for the view.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    return {
      restrict: 'A',
      scope: {
        metaproperty: '@'
      },
      link: function postLink(scope, element, attrs) {
        scope.default = element.attr('content');
        scope.metadata = metadataService;

        // Watch for metadata changes and set content
        scope.$watch('metadata', function (newVal, oldVal) {
          setContent(newVal);
        }, true);

        // Set the content attribute with new metadataService value or back to the default
        function setContent(metadata) {
          var content = metadata[scope.metaproperty] || scope.default;
          element.attr('content', content);
        }

        setContent(scope.metadata);
      }
    };

    索引文件

    完成了前面提到的硬编码的回退标签,对于无法获取任何javascript的爬虫程序。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <head>
      Fallback Title
      <meta name="description" metaproperty="description" content="Fallback Description">

      <!-- Open Graph Protocol Tags -->
      <meta property="og:url" content="fallbackurl.com" metaproperty="url">
      <meta property="og:title" content="Fallback Title" metaproperty="title">
      <meta property="og:description" content="Fallback Description" metaproperty="description">
      <meta property="og:type" content="website" metaproperty="ogpType">
      <meta property="og:image" content="fallbackimage.jpg" metaproperty="image">

      <!-- Twitter Card Tags -->
      <meta name="twitter:card" content="summary_large_image" metaproperty="twitterCard">
      <meta name="twitter:title" content="Fallback Title" metaproperty="title">
      <meta name="twitter:description" content="Fallback Description" metaproperty="description">
      <meta name="twitter:site" content="@fallback_handle" metaproperty="twitterSite">
      <meta name="twitter:image:src" content="fallbackimage.jpg" metaproperty="image">
    </head>

    这对大多数搜索引擎用例都会有很大帮助。如果你想要对社交网络爬虫进行全动态渲染(这在javascript支持上是不确定的),你仍然需要使用其他答案中提到的其中一个预渲染服务。

    希望这有帮助!


    使用Angular Universal,您可以为看起来像完整应用程序的应用程序生成登录页面,然后在其后面加载Angular应用程序。
    Angular Universal生成纯HTML意味着服务器端没有javascript页面,并且在不延迟的情况下为用户提供服务。所以你可以处理任何爬虫,机器人和用户(谁已经有低CPU和网络速度),然后你可以通过链接/按钮重定向到你的实际角度应用程序,已经加载在它后面。此解决方案由官方网站推荐。-有关SEO和Angular Universal的详细信息-


    使用类似prerender的方法,它可以生成网站的静态页面,以便搜索引擎对其进行索引。

    您可以在这里找到它的可用平台:https://prerender.io/documentation/install middleware_asp net


    爬虫程序(或bots)被设计为对网页的HTML内容进行爬行,但是由于异步数据获取的Ajax操作,这成为一个问题,因为需要一些时间来呈现网页并在上面显示动态内容。同样,AngularJS也使用异步模型,这给谷歌爬虫带来了问题。

    一些开发人员使用真实数据创建基本的HTML页面,并在爬行时从服务器端为这些页面提供服务。我们可以在服务器端呈现与PhantomJS相同的页面,服务器端有_escaped_fragment_(因为google在我们的站点URL中查找#!,然后在#!之后获取所有内容,并将其添加到_escaped_fragment_查询参数中)。有关详细信息,请阅读此博客。


    爬虫不需要一个功能丰富、样式美观的图形用户界面,它们只想看到内容,所以您不需要给它们一个为人类构建的页面的快照。

    我的解决方案:给爬虫想要什么:

    你必须想一想爬虫想要什么,只给它。

    小费不要弄脏后面。只需使用相同的API添加一点服务器端的前视图