获取元素的 CSS 选择器(当它没有 id 时)

Posted

技术标签:

【中文标题】获取元素的 CSS 选择器(当它没有 id 时)【英文标题】:Get element's CSS selector (when it doesn't have an id) 【发布时间】:2011-06-03 01:16:55 【问题描述】:

我正在尝试通过 javascript/CSS 修改页面(很像 Stylish 或 Greasemonkey 所做的)。这是一个非常复杂的页面(我没有构建,或者无法修改预渲染),这使得构建 CSS 选择器变得很困难(手动查看文档结构)。我怎样才能做到这一点?

【问题讨论】:

抱歉,您如何识别元素?还是您的意思是构建完整的 DOM 树? 我的最终目的是为对象创建一个 css 选择器。我可以查看页面代码并通过查看文档来推断此路径(来自 gmail.com “div.nH.T4.pp + div.pp + div.nH.pp.ps.TZ”的示例选择器),我想要一种方法来帮助我构建选择器。 嘿,rcphq,你找到解决这个问题的任何方法了吗?我也在寻找同样的东西。 为什么不使用它的 id 如果它有一个,或者如果它没有一个就分配一个新的 id? 这是一个比看起来更复杂的问题,有good libraries that solve it。此外,它是 Getting a jQuery selector for an element 的副本。 【参考方案1】:

如果元素是 div 表或 body..etc 中的第一个子元素,则可以用于 css first-child 伪类

你可以使用 jquery 的第 n 个 child() 函数。

http://api.jquery.com/nth-child-selector/

来自 jquery.com 的示例

<!DOCTYPE html>
<html>
<head>
  <style>

  div  float:left; 
  span  color:blue; 
  </style>
  <script src="http://code.jquery.com/jquery-1.4.4.js"></script>
</head>
<body>
  <div><ul>
    <li>John</li>
    <li>Karl</li>
    <li>Brandon</li>

  </ul></div>
  <div><ul>
    <li>Sam</li>
  </ul></div>

  <div><ul>
    <li>Glen</li>
    <li>Tane</li>
    <li>Ralph</li>

    <li>David</li>
  </ul></div>
<script>$("ul li:nth-child(2)").append("<span> - 2nd!</span>");</script>

</body>
</html>

如果我正确理解了这个问题,我的 2 美分。

【讨论】:

这可行,但我在我没有建立的页面上执行此操作,因此 id 需要以某种方式获得它是什么“nth-child”。这是我的主要问题。【参考方案2】:
function fullPath(el)
  var names = [];
  while (el.parentNode)
    if (el.id)
      names.unshift('#'+el.id);
      break;
    else
      if (el==el.ownerDocument.documentElement) names.unshift(el.tagName);
      else
        for (var c=1,e=el;e.previousElementSibling;e=e.previousElementSibling,c++);
        names.unshift(el.tagName+":nth-child("+c+")");
      
      el=el.parentNode;
    
  
  return names.join(" > ");


console.log(  fullPath( $('input')[0] ) );
// "#search > DIV:nth-child(1) > INPUT:nth-child(1)"

这似乎是您要求的,但您可能会意识到这并不能保证唯一标识一个元素。 (对于上面的示例,所有同级输入也将匹配。)

编辑:将代码更改为使用 nth-child 而不是 CSS 类来正确消除单个孩子的歧义。

【讨论】:

漂亮简洁的纯 js 函数 :) 请注意, :nth-child 在应用于 HTML 标记时将不起作用......或者至少我无法让它在 Firefox 或Chrome...我想这可能是由于 没有父级。 没问题,我也不会考虑这个问题:) 我已经提交了一个微妙的编辑,在你的新版本中将“HTML”更改为“html”......由于 .toLowerCase( ) 方法。 请注意,由于 CSS 选择器不允许选择 DOM 文本节点,因此此代码在这种情况下会产生错误的结果(el.tagName 将给出 undefined)。 不错...可能想将它打包到一个库中,或者可能改进 one 的 10+ ones 做同样的事情。 这将很好地工作,直到他们预先添加另一个孩子,这是 nth-child() 选择器的固有问题。我会使用特异性派生一个选择器。【参考方案3】:

使用安装了 FireBug 的 FireFox。

右键单击任何元素 选择“检查元素” 右键单击 HTML 树中的元素 选择“复制 XPath”或“复制 CSS 路径”

此答案的永久链接的输出 (XPath):

/html/body/div[4]/div[2]/div[2]/div[2]/div[3]/table/tbody/tr/td[2]/table/tbody/tr/ td/div/a

CSS 路径:

html body.question-page div.container div#content div#mainbar div#answers div#answer-4588287.answer table tbody tr td table.fw tbody tr td.vt div.post-menu a


但是关于这条评论:

我的最终目的是创建一个 CSS 对象的选择器...

如果这是您的意图,可能有更简单的 JavaScript 方法:

var uniquePrefix = 'isThisUniqueEnough_';
var counterIndex = 0;
function addCssToElement(elem, cssText)
    var domId;
    if(elem.id)domId=elem.id;
    else
        domId = uniquePrefix + (++counterIndex);
        elem.id = domId;
    
    document.styleSheets[0].insertRule("#"+domId+""+cssText+"");

最后一行可能需要针对不同的浏览器进行不同的实现。没有测试。

【讨论】:

谢谢,我使用的是 chrome 的 firebug (lite) 版本,但找不到这个选项。像魅力一样工作。【参考方案4】:

我发现我实际上可以使用this code from chrome devtools source 来解决这个问题,而无需进行太多修改。

在将 WebInspector.DOMPresentationUtils 中的相关方法添加到新命名空间并修复一些差异后,我简单地这样称呼它:

> UTILS.cssPath(node)

实现示例see css_path.js

【讨论】:

这是迄今为止我找到的最好的解决方案。为方便起见,我将其发布在 npm 上:npmjs.com/package/cssman @Macks:你愿意publish the source on GitHub吗? 其实Chromium code produces a lot of non-unique selectors。 如果非唯一意味着生成的选择器应返回 1 且仅返回 1 个元素,则操作从未明确要求它。但是应该很容易修改代码以检查同级并获取索引或其他不同的属性 为什么会产生非唯一的?我以为它做了第 n 个孩子的事情?【参考方案5】:

检查这个 CSS 选择器生成器库@medv/finder

生成最短选择器 每页的唯一选择器 稳定而健壮的选择器 2.9 kB gzip 并缩小大小

生成选择器示例:

.blog > article:nth-child(3) .add-comment

【讨论】:

【参考方案6】:

function getCssSelector(el)

    names = [];
    do 
        index = 0;
        var cursorElement = el;
        while (cursorElement !== null)
        
            ++index;
            cursorElement = cursorElement.previousElementSibling;
        ;
        names.unshift(el.tagName + ":nth-child(" + index + ")");
        el = el.parentElement;
     while (el !== null);

    return names.join(" > ");

【讨论】:

以上是关于获取元素的 CSS 选择器(当它没有 id 时)的主要内容,如果未能解决你的问题,请参考以下文章

怎样通过CSS选择器获取元素节点或元素节点集合

010. CSS 选择器

css如何选择没有定义class或者id的元素

jQuery选择器基础入门教程

css选择器执行的顺序是啥样的?

CSS 选择器