首先先稍微讲一下情况,大概就是写爬虫时使用querySelector选取元素时发现选取结果与预期不符
比如如下的情况
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>test</title>
</head>
<body>
<div>
<div>
</div>
<div id='content'>
<p>1</p>
<div>
<div></div>
<div>
<p>2</p>
</div>
</div>
</div>
</div>
在上面的html里使用
document.querySelector('#content').querySelector('div >div:nth-child(2) p')
然后直观的思考结果应该是下面的html界面中哪个元素?
第一感觉应该选取到的是<p>2</p>吧
然而选取结果是<p>1</p>
至于为什么会有这样的结果,困扰了我很久,知道看到一篇其他人的博客才稍微解开疑惑【博客地址于文章最后】
博客中概述了querySelector是先全局选取了所有符合querySelector('div >div:nth-child(2) p')的元素,然后再判断是否在document.querySelector('#content')中,如果在的话,则进行返回。
个人理解,即逻辑类似下面代码这样
var temp = document.querySelectorAll('div >div:nth-child(2) p');
temp = [].slice.call(temp);
var temp2 = document.querySelectorAll('#content *');
temp2 = [].slice.call(temp2);
for(ele of temp){
if(temp2.indexOf(ele) != -1){
console.log(ele);
break;
}
}
这个解释了一下为什么会这样。【参考自其它人博客,不知道哪里能找到querySelector源码之类的看,所以也不能百分百肯定这部分逻辑是否正确】
从这个逻辑推算,我最后得出的解决方案为
1.把选择器放在一起,不要分开查询(比较推荐)
例子中的document.querySelector('#content').querySelector('div >div:nth-child(2) p')
可以改为document.querySelector('#content div >div:nth-child(2) p')
当然大部分情况下都不是这样直接多重查询,选择的都是var temp = document.querySelector('#content')这种变量存储,然后多次使用,这里只是举例,可以把这些变量之前的值也一起选择
2.尽量缩小查询范围,避免误差
例子中的document.querySelector('#content').querySelector('div >div:nth-child(2) p')
可以改为document.querySelector('#content').querySelector('div >div:nth-child(2)').querySelector('p')
这种方法依然会可能有误差,但是可能比较小,因为查询范围已经被压缩了。这种情况用于,之前是通过函数传递值之类的,不方便修改选择器那些。但是依然有误差,所以注意测试