我看到AngularJS应用程序有关搜索引擎和搜索引擎优化的两个问题:
1)自定义标签会发生什么?搜索引擎会忽略这些标签中的所有内容吗?即假设我有
<custom>
<h1>Hey, this title is important</h1>
</custom>
将Qazxswpoi归类为自定义标签内部吗?
2)有没有办法避免索引{{}}的搜索引擎字面上绑定?即
<h1>
我知道我可以做点什么
<h2>{{title}}</h2>
但是,如果我想让爬虫“看到”标题怎么办?服务器端渲染是唯一的解决方案吗?
2014年5月更新
Google抓取工具<h2 ng-bind="title"></h2>
- 您可以使用now executes javascript更好地了解Google如何呈现您的网站。
原始答案 如果您想针对搜索引擎优化您的应用,很遗憾无法为抓取工具提供预渲染版本。您可以阅读更多关于Google对ajax和javascript-heavy网站Google Webmaster Tools的建议。
如果这是一个选项,我建议阅读here关于如何使用服务器端渲染为Angular做SEO。
我不确定爬虫在遇到自定义标签时会做什么。
Google的Crawlable Ajax Spec,在其他答案中引用,基本上就是答案。
如果你对其他搜索引擎和社交机器人如何处理同样的问题感兴趣,我在这里写下了艺术现状: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.
我为http://blog.ajaxsnapshots.com/2013/11/googles-crawlable-ajax-specification.html工作,这是一家实现Crawlable Ajax Spec作为服务的公司 - 该报告中的信息基于我们日志的观察结果。
我找到了一个优雅的解决方案,可以覆盖你的大部分基地。我最初写了https://ajaxsnapshots.com并回答了另一个类似的StackOverflow问题here,它引用了它。
仅供参考,此解决方案还包括硬编码的回退标记,以防爬虫无法获取Javascript。我没有明确地概述它,但值得一提的是,您应该激活HTML5模式以获得正确的URL支持。
另请注意:这些不是完整的文件,只是相关部分的重要部分。如果您需要帮助编写可在其他地方找到的指令,服务等的样板文件。无论如何,这里......
app.js
您可以在此处为每条路线提供自定义元数据(标题,说明等)
here
metadata-service.js(服务)
设置自定义元数据选项或使用默认值作为回退。
$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' }
})
metaproperty.js(指令)
打包视图的元数据服务结果。
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);
});
的index.html
完成前面提到的硬编码后备标记,对于无法获取任何Javascript的抓取工具。
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支持上不受欢迎)的完全动态渲染,您仍然必须使用其他一些答案中提到的预渲染服务之一。
希望这可以帮助!
使用类似PreRender的东西,它会生成您网站的静态页面,以便搜索引擎可以为其编制索引。
在这里,您可以找到它可用的平台:<head>
<title>Fallback Title</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>
使用Angular Universal,您可以为应用程序生成看起来像完整应用程序的登录页面,然后在其后面加载Angular应用程序。 Angular Universal生成纯HTML意味着服务器端的无javascript页面,并在不延迟的情况下将其提供给用户。因此,您可以处理任何爬虫,机器人和用户(已经具有低CPU和网络速度)。然后您可以通过链接/按钮将它们重定向到已经加载到其后面的实际角度应用程序。该解决方案由官方网站推荐。 https://prerender.io/documentation/install-middleware#asp-net
爬虫(或机器人)旨在抓取网页的HTML内容,但由于异步数据获取的AJAX操作,这成为一个问题,因为它需要一些时间来呈现页面并在其上显示动态内容。同样,-More info about SEO and Angular Universal-也使用异步模型,这会为Google抓取工具带来问题。
一些开发人员使用真实数据创建基本的html页面,并在爬行时从服务器端提供这些页面。我们可以在AngularJS
的服务端使用PhantomJS
渲染相同的页面(因为Google在我们的网站网址中查找_escaped_fragment_
,然后在#!
之后获取所有内容并将其添加到#!
查询参数中)。有关更多详细信息,请阅读此_escaped_fragment_
。
爬虫不需要富有特色的漂亮风格的gui,他们只想看内容,所以你不需要给他们一个为人类构建的页面的快照。
我的解决方案:为爬虫提供爬虫想要的东西:
你必须考虑爬虫想要的东西,并且只给他那个。
提示不要乱背。只需使用相同的API添加一个服务器端的前端视图
当前(2015)的方法是使用JavaScript pushState方法。
PushState更改顶部浏览器栏中的URL而不重新加载页面。假设您有一个包含标签的页面。选项卡隐藏和显示内容,并使用AJAX或简单地设置display:none和display:block来动态插入内容,以隐藏和显示正确的选项卡内容。
单击选项卡后,使用pushState更新地址栏中的URL。呈现页面时,使用地址栏中的值来确定要显示的选项卡。角度路由将自动为您执行此操作。
有两种方法可以访问PushState单页面应用程序(SPA)
网站上的初始点击将涉及直接点击URL。随着PushState更新URL,后续命中将只是内容中的AJAX。
抓取工具从页面中获取链接,然后将它们添加到队列中以供稍后处理。这意味着对于爬虫来说,服务器上的每次点击都是直接命中,它们不会通过Pushstate导航。
预合成将初始有效负载捆绑到服务器的第一个响应中,可能作为JSON对象。这允许搜索引擎在不执行AJAX调用的情况下呈现页面。
有证据表明Google可能不会执行AJAX请求。更多相关信息:
谷歌已经能够解析JavaScript一段时间了,这就是他们最初开发Chrome的原因,它可以作为谷歌蜘蛛的全功能无头浏览器。如果链接具有有效的href属性,则可以为新URL编制索引。没有什么可做的了。
如果另外单击链接会触发pushState调用,则用户可以通过PushState导航该站点。
目前,Google和Bing都支持PushState。
这是Matt Cutts回应Paul Irish关于SEO的PushState的问题:
以下是Google宣布对蜘蛛的完整JavaScript支持:
结果是Google支持PushState并将索引PushState URL。
另请参阅Google网站管理员工具的Googlebot抓取工具。您将看到您的JavaScript(包括Angular)已执行。
以下是Bing发布的支持2013年3月发布的漂亮PushState URL的消息:
http://googlewebmastercentral.blogspot.de/2014/05/understanding-web-pages-better.html
Hashbang网址是一个丑陋的权宜之计,需要开发人员在特殊位置提供网站的预渲染版本。它们仍然有效,但您不需要使用它们。
Hashbang网址如下所示:
http://blogs.bing.com/webmaster/2013/03/21/search-engine-optimization-best-practices-for-ajax-urls/
这将与这样的元标记配对:
domain.com/#!path/to/resource
Google不会以此形式对其进行索引,而是从_escaped_fragments_网址中提取该网站的静态版本并将其编入索引。
Pushstate URL看起来像任何普通的URL:
<meta name="fragment" content="!">
区别在于Angular通过拦截在JavaScript中处理它的document.location的更改来为您处理它们。
如果您想使用PushState URL(您可能会这样做),请取出所有旧的哈希样式URL和元标记,并在配置块中启用HTML5模式。
Google网站管理员工具现在包含一个工具,可以让您以谷歌的形式获取网址,并在Google呈现时呈现JavaScript。
domain.com/path/to/resource
要在Angular中生成真实URL而不是#prefixed,请在$ locationProvider对象上设置HTML5模式。
https://www.google.com/webmasters/tools/googlebot-fetch
由于您使用的是真实URL,因此您需要确保服务器为所有有效URL提供相同的模板(以及一些预先组合的内容)。如何执行此操作将取决于您的服务器体系结构。
您的应用可能会使用不寻常的导航形式,例如悬停或滚动。为了确保Google能够推动您的应用,我建议您创建一个站点地图,这是您的应用响应的所有网址的简单列表。您可以将其放在默认位置(/ sitemap或/sitemap.xml),或使用网站管理员工具告诉Google。
无论如何都有一个站点地图是个好主意。
Pushstate适用于IE10。在旧版浏览器中,Angular会自动回退到哈希样式的URL
使用带有预合成的pushstate URL呈现以下内容:
$locationProvider.html5Mode(true);
可以验证,在http://html5.gingerhost.com/london,内容已编入索引并出现在Google中。
由于搜索引擎会始终针对每个请求点击您的服务器,因此您可以从服务器提供标头状态代码,并希望Google能够看到它们。
Google,Yahoo,Bing和其他搜索引擎使用传统抓取工具以传统方式抓取网络。他们运行机器人,在网页上抓取HTML,沿途收集信息。他们保留有趣的单词,并寻找其他页面的其他链接(这些链接,它们的数量和它们的数量与SEO发挥作用)。
答案与搜索引擎机器人通过无头浏览器工作这一事实有关,而且他们通常没有javascript渲染引擎来呈现页面的javascript。这适用于大多数页面,因为大多数静态页面不关心JavaScript呈现其页面,因为它们的内容已经可用。
幸运的是,大型网站的抓取工具已经开始实施一种机制,允许我们使我们的JavaScript网站可抓取,但它要求我们对我们的网站实施更改。
如果我们将this link改为hashPrefix
而不仅仅是#!
,那么现代搜索引擎将改变使用#
而不是_escaped_fragment_
的请求。 (使用HTML5模式,即我们有没有哈希前缀的链接,我们可以通过查看后端的#!
头来实现这个功能)。
也就是说,而不是来自普通浏览器的请求,而不是:
User Agent
搜索引擎将搜索该页面:
http://www.ng-newsletter.com/#!/signup/page
我们可以使用http://www.ng-newsletter.com/?_escaped_fragment_=/signup/page
中的内置方法设置Angular应用程序的哈希前缀:
ngRoute
而且,如果我们使用angular.module('myApp', [])
.config(['$location', function($location) {
$location.hashPrefix('!');
}]);
,我们需要使用meta标签来实现:
html5Mode
提醒一下,我们可以使用<meta name="fragment" content="!">
服务设置html5Mode()
:
$location
我们有很多机会确定我们如何处理实际向搜索引擎提供内容的静态HTML。我们可以自己托管后端,我们可以使用服务为我们托管后端,我们可以使用代理来提供内容等。让我们看几个选项:
我们可以编写一个服务来处理使用无头浏览器(如phantomjs或zombiejs)爬行我们自己的站点,使用呈现的数据拍摄页面的快照并将其存储为HTML。每当我们在搜索请求中看到查询字符串angular.module('myApp', [])
.config(['$location',
function($location) {
$location.html5Mode(true);
}]);
时,我们就可以通过JS传递我们对页面而不是预呈现页面的静态HTML快照。这要求我们有一个后端,在中间提供带有条件逻辑的页面。我们可以使用像?_escaped_fragment_
后端这样的东西作为自己运行的起点。当然,我们仍然需要处理代理和代码段处理,但这是一个好的开始。
将内容引入搜索引擎的最简单,最快捷的方法是使用服务prerender.io's,Brombone,seo.js和seo4ajax就是这些将为您提供上述内容呈现的好例子。对于我们不想处理运行服务器/代理的时候,这是一个很好的选择。而且,它通常超级快。
有关Angular和SEO的更多信息,我们在prerender.io上编写了一个关于它的广泛教程,我们在我们的书籍:AngularJS的完整书中详细介绍了它。在http://www.ng-newsletter.com/posts/serious-angular-seo.html查看。
您应该在moo博客年度查看有关构建SEO友好的AngularJS网站的教程。他将引导您完成Angular文档中列出的所有步骤。 ng-book.com
使用此技术,搜索引擎会看到扩展的HTML而不是自定义标记。
这已经发生了巨大的变化。
http://www.yearofmoo.com/2012/11/angularjs-and-seo.html
如果您使用:$ locationProvider.html5Mode(true);你被设定了。
没有更多的渲染页面。
自从提出这个问题以来,情况发生了很大的变化。现在有选项让Google为您的AngularJS网站编制索引。我找到的最简单的选择是使用http://searchengineland.com/bing-offers-recommendations-for-seo-friendly-ajax-suggests-html5-pushstate-152946免费服务,它将为您生成crwalable页面并将其提供给搜索引擎。它几乎在所有服务器端Web平台上都受支持。我最近开始使用它们,支持也非常好。
我与他们没有任何关系,这来自一个快乐的用户。
Angular自己的网站为搜索引擎提供简化的内容:http://prerender.io
假设您的Angular应用程序正在使用Node.js / Express驱动的JSON API,例如http://docs.angularjs.org/?_escaped_fragment_=/tutorial/step_09。也许您可以使用/api/path/to/resource
将任何请求重定向到?_escaped_fragment_
,并使用/api/path/to/resource.html
呈现内容的HTML模板,而不是返回JSON数据。
唯一的问题是,你的Angular路由需要与你的REST API 1:1匹配。
编辑:我意识到这有可能真的让你的REST api变得混乱,我不建议在非常简单的用例之外做它,这可能是一个很自然的选择。
相反,您可以为机器人友好的内容使用完全不同的路由和控制器集。但是,您将在Node / Express中复制所有AngularJS路由和控制器。
我已经决定使用无头浏览器生成快照,尽管我觉得这有点不太理想。
这里有一个很好的做法:
截至目前,谷歌已经改变了他们的AJAX抓取建议。
http://scotch.io/tutorials/javascript/angularjs-seo-with-prerender-io?_escaped_fragment_=tag
tl;博士:[Google]不再推荐2009年制作的AJAX抓取提案[Google]。