.htaccess为SEO机器人抓取单页应用程序没有hashbangs

时间:2013-07-29 14:07:14

标签: javascript .htaccess web-crawler single-page-application

使用pushState启用的页面,通常使用escaped_fragment约定重定向SEO机器人。您可以详细了解 here

该约定假设您将在单个页面应用程序上的所有URI之前使用(#!)hashbang前缀。 SEO机器人会在发出页面请求时用它自己的可识别约定escaped_fragment替换hashbang来逃避这些片段。

//Your page
http://example.com/#!home

//Requested by bots as
http://example.com/?_escaped_fragment=home

这允许站点管理员检测机器人,并将它们重定向到缓存的预渲染页面。

RewriteCond %{QUERY_STRING} ^_escaped_fragment_=(.*)$
RewriteRule ^(.*)$  https://s3.amazonaws.com/mybucket/$1 [P,QSA,L]

问题在于,随着广泛适应的pushState支持,hashbang正在逐步淘汰。它也非常丑陋,对用户来说不是很直观。

那么如果我们使用HTML5模式,其中pushState引导整个用户应用程序呢?

//Your index is using pushState
http://example.com/

//Your category is using pushState (not a folder)
http://example.com/category

//Your category/subcategory is using pushState
http://example.com/category/subcategory

可以使用这个较新的约定重写规则引导机器人到您的缓存版本吗? Related but only accounts for index edge case. Google还 has an article ,建议在{{1}中使用<meta name="fragment" content="!">对此单边案例使用 opt-in 方法页面的。同样,这是针对单边案例的。在这里,我们讨论的是将每个页面作为 opt-in senario处理。

<head>

我认为http://example.com/?escaped_fragment= http://example.com/category?escaped_fragment= http://example.com/category/subcategory?escaped_fragment= 仍然可以用作SEO机器人的标识符,并且我可以提取域和此标识符之间的所有内容,以附加到我的存储桶位置,如:

escaped_fragment

处理此问题的最佳方法是什么?

4 个答案:

答案 0 :(得分:1)

在单页网页应用上遇到类似的问题。

我发现这个问题的唯一解决方案是有效地创建页面的静态版本,目的是让谷歌(和其他)机器人可以导航。

你可以自己做,但也有一些服务可以做到这一点并为你创建静态缓存(并通过他们的CDN向机器人提供快照)。

我最终使用了SEO4Ajax,虽然其他类似的服务可用!

答案 1 :(得分:0)

我遇到了完全相同的问题。现在,我已经像这样修改了.htaccess:

RewriteCond %{QUERY_STRING} ^_escaped_fragment_=(.*)$
RewriteRule ^$ /snapshots/index.html? [L,NC]
RewriteCond %{QUERY_STRING} ^_escaped_fragment_=(.*)$
RewriteRule ^(.*)$ /snapshots/$1.html? [L,NC]

不确定是否有更好的解决方案,但到目前为止它对我有用。 请确保快照的目录结构与网址结构匹配。

答案 2 :(得分:0)

我正在使用Symfony2,虽然其他开发人员告诉我们Googlebot和Bingbot能够很好地执行Javascript以生成自己的HTML代码段,但我并不自信。我也觉得服务静态资源对于运行JS关闭的ppl来说是一个更好的选择(但不太可能),因此无论如何都对提供HTML片段感兴趣,只要它不麻烦。以下是我想要使用但尚未尝试的方法:

以下是其他类似的问题(一个是我的)。
Angularjs vs SEO vs pushState
HTML snippets for AngularJS app that uses pushState?

这是我在该问题中发布的解决方案,我正在考虑自己,以防我想向机器人发送HTML代码段。这将是 Symfony2后端的解决方案:

  1. 使用预渲染或其他服务生成所有网页的静态代码段。将它们存放在路由器可以访问的地方。
  2. 在Symfony2路由文件中,创建一个与您的SPA匹配的路由。我在localhost.com/ng-test/上运行了一个测试SPA,所以我的路线看起来像这样:

    # Adding a trailing / to this route breaks it. Not sure why.
    # This is also not formatting correctly in StackOverflow. This is yaml.
    NgTestReroute:
    ----path: /ng-test/{one}/{two}/{three}/{four}
    ----defaults:
    --------_controller: DriverSideSiteBundle:NgTest:ngTestReroute
    --------'one': null
    --------'two': null
    --------'three': null
    --------'four': null
    ----methods: [GET]

  3. 在Symfony2控制器中,检查用户代理以查看它是googlebot还是bingbot。您应该可以使用下面的代码执行此操作,然后使用此列表定位您感兴趣的机器人(http://www.searchenginedictionary.com/spider-names.shtml)...

    if(strstr(strtolower($_SERVER['HTTP_USER_AGENT']), "googlebot"))
    {
        // what to do
    }

  4. 如果您的控制器找到与机器人匹配的内容,请将其发送给HTML代码段。否则,就像我的AngularJS应用程序一样,只需将用户发送到索引页面,Angular就会正确完成剩下的工作。

  5. 此外,如果您的问题已经得到解答,请选择一个,以便我和其他人可以说出对您有用的问题。

答案 3 :(得分:0)

我正在使用PhantomJS生成页面的静态快照。我的目录结构只有一层深(root/projects),所以我有两个.htaccess文件,我在其中重定向到启动PhantomJS进程的PHP文件(index-bots.php)指向我的SPA index.html并打印出渲染的静态页面。

.htaccess文件如下所示:

<强> /。htaccess的

# redirect search engine bots to index-bots.php
# in order to serve rendered HTML via phantomjs
RewriteCond %{HTTP_USER_AGENT} (bot|crawl|slurp|spider) [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !^/index-bots\.php [NC]
RewriteRule ^(.*)$ index-bots.php?url=%{REQUEST_URI} [L,QSA]

<强> /projects/.htaccess

# redirect search engine bots to index-bots.php
# in order to serve rendered HTML via phantomjs
RewriteCond %{HTTP_USER_AGENT} (bot|crawl|slurp|spider) [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ ../index-bots.php?url=%{REQUEST_URI} [L,QSA]

几点说明:

  • !-f RewriteCond至关重要!由于.htaccess会将RewriteRule应用于所有请求,因此页面上的资源将被重写为PHP文件,从而启动PhantomJS的多个实例并使您的服务器瘫痪。
  • 从重写中豁免index-bots.php以避免无限循环也很重要。
  • 我在我的PhantomJS跑步者脚本中删除了JS,以确保当支持它的机器人遇到“静态”页面时,JS不会做任何事情。
  • 我不是.htaccess向导,所以可能有更好的方法来做到这一点。如果是的话,我很想听。