【问题标题】:robots.txt file for different domains of same site同一站点的不同域的 robots.txt 文件
【发布时间】:2013-06-06 16:38:01
【问题描述】:

我有一个可以从多个不同域访问的 ASP.NET MVC 4 Web 应用程序。该站点基于请求中的域完全本地化(在概念上类似于this question)。

我想包含一个 robots.txt 文件,并且我想根据域对 robots.txt 文件进行本地化,但我知道我在站点的文件系统中只能有一个物理“robots.txt”文本文件目录。

使用 ASP.NET MVC 框架在每个域的基础上实现 robots.txt 文件的最简单/最好的方法(甚至可能)是什么,以便相同的站点安装为每个域提供内容,但是 robots 文件的内容会根据请求的域进行本地化?

【问题讨论】:

  • 我不认为这个问题应该已经结束:这是一个与 asp.net MVC 相关的编程问题,并且正是 ASP.NET 管道适合解决的问题类型:如何就要服务的内容做出上下文决策。这绝对不是题外话。

标签: asp.net-mvc-4 seo robots.txt


【解决方案1】:

这个过程相当简单:

控制器/动作方法

  • 使用您的路由表,将您的 robots.txt 路径映射到控制器中的操作(我使用控制器和操作作为一个简单的示例来帮助您入门),就像您对给定路径的任何其他控制器和视图一样。
  • 在操作中,检查请求中的域并为该域选择您的 robots.txt 内容。
  • 使用以下方法从磁盘返回适当的文件:

以下示例假定一个顶级 robots.txt 文件:

// In App_Start/RouteConfig:
public static void RegisterRoutes(RouteCollection routes)
{
  routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
  routes.MapRoute(
    name: "robots",
    url: "robots.txt",
    defaults: new { controller = "Seo", action = "Robots" }
);

// The controller:
public class SeoController : Controller {
  public ActionResult Robots() {
    var robotsFile = "~/robots-default.txt";
    switch (Request.Url.Host.ToLower()) {
      case "stackoverflow.com":
        robotsFile = "~/robots-so.txt";
        break;
      case "meta.stackoverflow.com":
        robotsFile = "~/robots-meta.txt";
        break;
    }
    return File(robotsFile, "text/plain");
  }
}

实现此功能的最简单方法之一是确保在 web.config 中使用 runAllManagedModulesForAllRequests 为所有请求调用路由模块(不要使用它,请参阅下一段):

<system.webServer>
  <handlers>
    ...
  </handlers>
  <modules runAllManagedModulesForAllRequests="true" />
</system.webServer>

一般来说不是一件好事,因为现在所有的静态文件(css、js、txt)在被转移到静态文件处理程序之前都会经过托管处理程序。 IIS真的擅长快速提供静态文件(一个主要是静态文件的网站会在 CPU 之前最大限度地利用你的磁盘 I/O),所以为了避免这种性能损失,推荐的方法是 web.xml 。下面的配置示例部分。请注意与 Visual Studio MVC 4 模板应用程序中的 ExtensionlessUrlHandler-Integrated-4.0 处理程序的相似之处:

<system.webServer>
  <handlers>
    <add name="Robots-Integrated-4.0"
         path="/robots.txt" verb="GET" 
         type="System.Web.Handlers.TransferRequestHandler" 
         preCondition="integratedMode,runtimeVersionv4.0" />
    ... the original handlers ...
  </handlers>
  <modules runAllManagedModulesForAllRequests="false" />
</system.webServer>       

优点/缺点

一旦你开始使用这种方法,它的优势就会显现出来:

  • 您可以动态生成 robots.txt 文件,方法是使用帮助程序生成操作 url,然后您可以将其全部/部分添加到模板 robots.txt 文件中。
  • 您可以检查机器人用户代理以针对每个机器人用户代理返回不同的机器人文件
  • 您可以使用相同的控制器为网络爬虫输出 sitemap.xml 文件
  • 您可以从网站用户可以轻松管理的数据库表中管理机器人内容。

不利的一面,

  • 您的 robots 文件现在使您的路由表变得复杂,实际上并不需要
  • 您需要优化缓存以防止持续的磁盘读取。但是,这对于您采取的任何方法都是一样的。

还请记住,不同的 robots.txt 文件可用于不同的子目录。这对于路由和控制器方法变得很棘手,因此IHttpHandler 方法(如下)在这种情况下更容易。

IHttpHandler 方法

您也可以使用自定义 IHttpHandler registered in your web.config 来执行此操作。我强调 custom 因为这避免了让所有控制器看到所有请求的需要(使用runAllManagedModulesForAllRequests="true",这与在路由表中添加自定义路由处理程序不同。

这也可能是一种比控制器更轻量级的方法,但您必须拥有巨大的网站流量才能注意到差异。它的另一个好处是一段可重用的代码,您可以将其用于所有站点。您还可以添加自定义配置部分来配置机器人用户代理/域名/路径映射到机器人文件。

<system.webServer>
  <handlers>
    <add name="Robots" verb="*" path="/robots.txt"
         type="MyProject.RobotsHandler, MyAssembly" 
         preCondition="managedHandler"/>
  </handlers>
  <modules runAllManagedModulesForAllRequests="false" />
</system.webServer>
public class RobotsHandler: IHttpHandler
{
  public bool IsReusable { get { return false; } }
  public void ProcessRequest(HttpContext context) {
    string domain = context.Request.Url.Host;
    // set the response code, content type and appropriate robots file here
    // also think about handling caching, sending error codes etc.
    context.Response.StatusCode = 200;
    context.Response.ContentType = "text/plain";

    // return the robots content
    context.Response.Write("my robots content");
  }
}

robots.txt 在子目录中

要为子目录和站点根目录提供机器人,您不能轻易使用控制器方法;在这种情况下,处理程序方法更简单。这可以配置为将 robots.txt 文件请求提取到任何子目录并相应地处理它们。然后,您可以选择为某些目录返回 404,或者为其他目录返回 robots 文件的子部分。

我在这里特别提到这一点,因为这种方法也可用于 sitemap.xml 文件,为站点的不同部分提供不同的站点地图,多个相互引用的站点地图等。


其他参考资料:

【讨论】:

  • 这非常有帮助,感谢 Andy 做出如此棒的回答。我想补充一点:您需要从根目录中删除 robots.txt,否则您将得到 500 错误递归深度执行。
  • 请问type="System.Web.Handlers.TransferRequestHandler"preCondition="integratedMode,runtimeVersionv4.0" 是什么意思?我讨厌在那里看到版本号。这让我觉得当我升级到新版本时我需要重写我的代码。 (而且,令人惊讶的是,我宁愿不必这样做。)
  • 我同意@JonathanWood,我们如何知道要使用哪些版本号,尤其是在云环境中,以及我们如何处理版本的变化?
【解决方案2】:

由于我工作的环境,Andy Brown 在 web.config 方法中的 System.Web.Handlers.TransferRequestHandler 方法对我不起作用,导致 500 错误。

使用 web.config url 重写规则的替代方法对我有用:

<rewrite>
    <rules>
        <rule name="Dynamic robots.txt" stopProcessing="true">
            <match url="robots.txt" />
            <action type="Rewrite" url="/DynamicFiles/RobotsTxt" />
        </rule>
    </rules>
</rewrite>

【讨论】:

    猜你喜欢
    • 2014-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-12
    • 2014-12-06
    • 2017-12-21
    • 1970-01-01
    • 2011-09-19
    相关资源
    最近更新 更多