看完Google's policy on making Ajax-generated content crawlable ,连同许多开发人员的博客文章和关于该主题的 Stackoverflow Q&A 线程,我得出的结论是,没有办法让仅使用 JavaScript/Ajax 生成的 HTML 的网站可抓取。我目前工作的网站没有将相当多的内容编入索引。我们非索引内容的所有表示层都是用 JavaScript 构建的,通过从基于 Ajax 的网络服务调用返回的 JSON 生成 HTML,我们相信 Google 不会因此索引内容。对吗?
唯一的解决方案似乎是为搜索引擎(特别是谷歌)提供一个“后备”版本的网站,所有 HTML 和内容都将像传统上那样在服务器端生成。对于启用了 JavaScript 的客户端,我们似乎可以使用与现在基本相同的方法:使用 JavaScript 从异步加载的 JSON 生成 HTML。
四处阅读,我的理解是当前应用 DRY principle 的最佳实践如上所述创建可抓取的 Ajax 生成的网站是使用模板引擎,该引擎可以在客户端和服务器端使用相同的模板。对于启用了 JavaScript 的客户端,客户端模板引擎,例如 mustache.js , 将从服务器发送的 JSON 数据转换为由其模板文件副本定义的 HTML。对于禁用 JavaScript 的搜索爬虫和客户端,相同模板引擎的服务器端实现,例如 mustache.java , 将类似地对其相同模板文件的副本进行操作以输出 HTML。
如果该解决方案是正确的,那么这与 4 或 5 年前重前端网站使用的方法有何不同,在这些网站中,网站基本上必须维护模板代码的两份副本,一份供启用了 JavaScript 的用户使用(几乎所有人)和另一个副本(例如 FreeMarker 或 Velocity )用于没有启用 JavaScript 的搜索引擎和浏览器(几乎没有)?看来应该有更好的办法。
这是否意味着需要维护两个模板模型层,一个在客户端,一个在服务器端?将这些客户端模板与前端 MVC (MV/MVVC) 框架结合起来是多么明智 Backbone.js , Ember.js , 或 YUI App Library ?这些解决方案如何影响维护成本?在不将更多框架(新的模板引擎和前端 MVC 框架)引入开发团队的技术堆栈的情况下尝试这样做会更好吗?有没有办法减少冗余?
如果该解决方案不正确,那么我们是否遗漏了一些东西并且可以使用我们的 JavaScript 做得更好,以保持我们现有的异步 HTML-from-JSON 结构并将其编入索引,因此我们不需要向架构堆栈引入一些新东西?当业务需求发生变化时,我们真的不想更新两个版本的表示层。
最佳答案
我以前怎么没想到呢!只需使用 http://phantomjs.org .这是一个 headless 的 webkit 浏览器。您只需构建一组操作来抓取 UI 并在您想要的每个状态下捕获 html。 Phantom 可以为您将捕获的 html 转换为 .html 文件,并将它们保存到您的网络服务器。
整个过程将在每次构建/提交时自动完成(PhantomJS 是命令行驱动的)。当您更改 UI 时,您编写的用于抓取 UI 的 JS 代码会中断,但它不应该比自动化 UI 测试差多少,而且它只是 Javascript,因此您可以使用 jQuery 选择器来抓取按钮并单击它们。
如果我必须解决 SEO 问题,这绝对是我首先采用的方法原型(prototype)。爬行并保存,宝贝。是的,先生。
关于model-view-controller - 使具有 JavaScript 生成的 HTML 的网站可抓取的最不冗余的方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10213185/
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
这似乎应该有一个直截了当的答案,但在Google上花了很多时间,所以我找不到它。这可能是缺少正确关键字的情况。在我的RoR应用程序中,我有几个模型共享一种特定类型的字符串属性,该属性具有特殊验证和其他功能。我能想到的最接近的类似示例是表示URL的字符串。这会导致模型中出现大量重复(甚至单元测试中会出现更多重复),但我不确定如何让它更DRY。我能想到几个可能的方向...按照“validates_url_format_of”插件,但这只会让验证干给这个特殊的字符串它自己的模型,但这看起来很像重溶液为这个特殊的字符串创建一个ruby类,但是我如何得到ActiveRecord关联这个类模型
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何
我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>