代码之家  ›  专栏  ›  技术社区  ›  Chris Mullins

让搜索引擎索引链接的最佳方法是什么?这些链接只在需要javascript才能访问的页面上可见。

  •  1
  • Chris Mullins  · 技术社区  · 15 年前

    假设我有一个ASP.NET Web窗体网站,我有一个页面化的网格视图。在GridView中,有指向网站中其他页面的链接,这些链接可能是整个网站中指向此内容的唯一链接。目前,谷歌和其他搜索引擎可能只能跟踪第一页上出现的链接,因为GridView寻呼机生成的链接如下:

    <a href="javascript:__doPostBack('GridTest','Page$2')">2</a>
    

    因此,谷歌将永远无法加载其他网页来爬行链接。

    我需要一个快速和肮脏的方式,谷歌索引所有可能隐藏在这些javascript链接下的页面。

    我已经考虑过在CSS中创建一个可见性关闭的链接,该链接将加载网格视图,其中所有记录都可见,没有分页。这是一个很好的解决方法吗?

    如果我有这个隐藏链接,我怎么能阻止搜索引擎索引那个页面(因为我不希望普通访问者访问它),但仍然跟踪和索引它链接到的页面。

    有人有什么想法吗?谢谢你的帮助。

    我喜欢科林的主意。我已经在使用自定义寻呼机控件,因此可以控制寻呼链接。为了实现他的建议,我为链接按钮创建了一个控件适配器,如果您给它一个,它将允许它呈现href属性,并将回发的javascript放在onclick中(但是它使它成为这样,您就不能同时使用onclientclick属性)。

    using System;
    using System.Collections.Generic;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.Adapters;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.Adapters;
    
    /// <summary>
    /// This adapter allows us to specify the href attribute and have it rendered on the page.  
    /// When the href is specified the postback javascript will go into the onclick.  The javascript will 
    /// cancel the href so it will post back like normal , but for people without javascript 
    /// the link should work, and search crawlers should be able to index the links
    /// 
    /// Styles that you can set like Font-Bold and Font-Underline are not going to work
    /// you will need to use the style attribute, or set it in css
    /// 
    /// </summary>
    public class LinkButtonAdapter : WebControlAdapter
    {
        protected override void Render(HtmlTextWriter writer)
        {
    
            LinkButton linkButton = (LinkButton)Control;
            if (linkButton != null)
            {
    
    
    
                writer.WriteBeginTag("a");
                writer.WriteAttribute("id", linkButton.ClientID);
    
                if (!string.IsNullOrEmpty(linkButton.ToolTip))
                {
                    writer.WriteAttribute("title", linkButton.ToolTip);
                }
    
    
                if (!string.IsNullOrEmpty(linkButton.CssClass))
                {
                    writer.WriteAttribute("class", linkButton.CssClass);
                }
    
                if (!string.IsNullOrEmpty(linkButton.Attributes["style"]))
                {
                    writer.WriteAttribute("style", linkButton.Attributes["style"]);
                }
    
                if (linkButton.Enabled)
                {
    
    
    
    
                    if (!string.IsNullOrEmpty(linkButton.Attributes["href"]))
                    {
                        //if the user has set the href render it, and render the javascript in the onclick
                        //this will negate the client click script so be careful
                        writer.WriteAttribute("href", linkButton.Attributes["href"]);
                        string ClientScript = Page.ClientScript.GetPostBackClientHyperlink(linkButton, "");
                        if (!string.IsNullOrEmpty(ClientScript))
                        {
                            writer.WriteAttribute("onclick", ClientScript + ";return false;");
                        }
    
                    }
                    else
                    {
                        writer.WriteAttribute("href", Page.ClientScript.GetPostBackClientHyperlink(linkButton, ""));
                        if (!string.IsNullOrEmpty(linkButton.OnClientClick))
                        {
                            writer.AddAttribute(HtmlTextWriterAttribute.Onclick, linkButton.OnClientClick);
                        }
                    }
                }
                else
                {
                    writer.WriteAttribute("disabled", "disabled");
                }
    
    
    
    
    
                writer.Write(HtmlTextWriter.TagRightChar);
    
                //apparently link buttons can contain other controls, who knew
                //when they are databound, and you have the expression in between the
                //tags it gets created as a LiteralControl
    
                //the behavior for linkbuttons seems to be to overwrite whatever
                //you set in the text propery with what is in between the begin and end tags
                //
                //Unless you have a databound control, then the text and the inner text seems 
                //to be concatenated together, which seems weird
                //
                //Also sometimes it generates literalcontrols, but removes them, and sometime it leave them
                //but only if you have another non literal control inside
                //
                //I don't want to try to emulate this right now it is too confusing.  
                //Just don't use the text and the inner html at the same time, and I am leaving all controls
                //that have been added          
    
                foreach (Control c in linkButton.Controls)
                {
                    if (c is LiteralControl)
                    {
                        linkButton.Text = ((LiteralControl)c).Text;
                    }
                    else if (c is DataBoundLiteralControl)
                    {
                        linkButton.Text = ((DataBoundLiteralControl)c).Text;
                    }
                    else
                    {
                        c.RenderControl(writer);
                    }
                }
    
                writer.Write(linkButton.Text);
    
                writer.WriteEndTag("a");
    
                Page.ClientScript.RegisterForEventValidation(linkButton.UniqueID);
    
            }
    
        }
    
    }
    

    然后将其放入浏览器文件:

    <browsers>
    
        <browser refID="Default">
            <controlAdapters>
                <adapter controlType="System.Web.UI.WebControls.LinkButton"
                         adapterType="LinkButtonAdapter" />
            </controlAdapters>
        </browser>
    
    </browsers>
    
    3 回复  |  直到 15 年前
        1
  •  2
  •   Colin    15 年前

    子类化GridView控件,重写呈现方法,然后使寻呼机的Href指向所需的页面(即 Default.aspx?Page=2 ,并将原始的href javascript链接复制到onclick事件。

    所以你的链接会变成

    <a href="Page2.aspx" onclick="javascript:__doPostBack('GridTest','Page$2')">Page 2</a>
    

    现在重要的是,附加 return false; 到onclick事件,所以它将成为

    <a href="Page2.aspx" onclick="javascript:__doPostBack('GridTest','Page$2');return false;">Page 2</a>
    

    因为onclick方法总是首先被调用,它将触发postback,但是 return false 将结束对 href 属性。这样,ASP.NET得到了它的回发,而Google得到了它的href。

    现在,为了 重要的是:您需要确保GridView响应 Request.QueryString["Page"] 价值也一样,否则整个练习就没有意义了,会不会有,因为谷歌不会看到第二页的内容?

        2
  •  0
  •   NickFitz    15 年前

    谷歌和其他搜索引擎对包含隐藏链接的网页或对人隐藏但显示给搜索引擎的网页的想法非常不满,因为它们是一种标准的垃圾邮件技术。你更有可能把这个网站列入黑名单。

    ASP.NET真的不能生成可以遵循的链接吗?除此之外,禁用javascript的用户也不能使用该站点。

    我用了ASP.NET已经有一段时间了(当时我写了所有我自己的控件,因为当时微软的控件太可怕了),但是你可以通过子类化控件并重写其呈现方法来创建可操作的链接。真的没有理由用脚本来模拟导致HTTP GET的简单链接,从而使用HTTP POST提交表单。

        3
  •  0
  •   Al Crowley    15 年前

    您可以将页面的非javascript版本转储到<noscript>标记中。这样链接就可以被任何浏览器或机器人看到。作为一个特别的额外奖励,你甚至可以让那些不能使用javascript的人访问它。例如,盲人使用文本来刺穿观看者。