一、querySelector()与querySelectorAll()
1、querySelector()
querySelector方法是浏览器提供的一个用于选择元素的方法,可以通过CSS选择器指定要选择的元素。该方法接收一个CSS选择器作为参数,返回选择器匹配到的第一个元素。
//1、HTML中的类名选择
let one =document.querySelector(".classname");//选择class中的元素用.去标识。
//2、HTML中的 ID选择
let two = document.querySelector("#idname");//选择id中的元素用#去标识。
//3、HTML中的标签选择
let three = document.querySelector("div");//选择id中的元素用#去标识。
以bilibili.com为例:
如想要获取id名为剑威之下此人的评论内容。
我们可以使用querySelector()方法,采用上述方法中类名选择方法,首先定位评论的类名在哪里,在Chrome里我们可以直接右击评论处点击检查直接定位他评论所属的class,这里我们定位到他的类名为"reply-content",所以我们使用方法如下:
let one = document.querySelector(".reply-content");
console.log(one.textContent);//console为控制台,console.log为控制台输出。这里我们输出one里面的文本内容textContent。
如上图所示,控制台能够输出所选中的文本。querySelector返回的是选择器匹配到的第一个元素。所以返回的是id名为剑威之下的评论内容(因为他是第一个评论)。
要是想要获取魔王李相赫的id,也就是第二个元素,我们就需要一些操作。queryselector不仅支持单个选择器,还支持多个选择器组合。
let one = document.querySelector(".user-name[data-user-id='228954485']");//选择class为uesr-name和自定义属性值data-user-id的选择器组合,在querySelector中自定义属性需要加[],在[]中添加自定义的属性值。
console.log(one.textContent);
除此之外querySelector()还支持伪类选择器如:
let one = document.querySelector("div:nth-child(5) >div.root-reply-container");//div:nth-child(5)表示第五个div元素。同时要根据后面的一起去定位,这里表示div含有root-reply-container的第五个div元素。所以越能定位子元素越能确定所需的文本。
console.log(one.innerText);//就是datanews里面的innerText方法
所以这个表示的为第五个评论的容器,然后我们使用innerText方法取出里面的内容。
这些方法也可以组合使用。如果想批量爬取网页中的评论内容,我们可以使用querySelectorAll()方法。
2、querySelectorAll()
querySelectorAll() 方法返回文档中匹配指定 CSS 选择器的所有元素,返回 NodeList对象,NodeList 对象表示节点的集合。可以通过索引访问,索引值从 0 开始;所以这个集合可以使用循环操作去操作它。
比如我们想爬取这个页面所有的评论。
let llist = document.querySelectorAll(".reply-content");
let text1 ="";
for(let i = 0; i<llist.length;i++)
{
text1 += llist[i].textContent+"\n"; //使用for循环来遍历我们已经取到的nodelist集合,然后将其中的文本内容输出,每个添加一个换行符这样保证每条评论一条一条显示。
}
console.log(text1);
这样爬取出来的会有回复的评论,如果只想要主评论。
let llist = document.querySelectorAll("div.root-reply-container > div.content-warp > div.root-reply > span > span");//控制只要主评论的内容。
let text1 ="";
for(let i = 0; i<llist.length;i++)
{
text1 += llist[i].innerText+"\n"; //使用for循环来遍历我们已经取到的nodelist集合,然后将其中的文本内容输出,每个添加一个换行符这样保证每条评论一条一条显示。
}
console.log(text1);
这样爬取的时候没有评论者的id,但其实可以两个都单独爬,第几条评论就对应第几个id即可。如果想打印的时候加上id我们就得多使用一些javascript代码了。
let llist = document.querySelectorAll("div.root-reply-container > div.content-warp > div.root-reply > span > span");//控制只要主评论的内容。
let text1 = [];//将评论存储为一个string数组
let text2 = [];//将id存储为一个string数组
let namelist = document.querySelectorAll(".user-name");
for(let i = 0; i<namelist.length;i++)
{
text2[i] = namelist[i].textContent;
}
for(let i = 0; i<llist.length;i++)
{
text1[i] += llist[i].innerText;
}
for(let i=0;i<namelist.length();i++)
{
console.log(text2[i]);
console.log(text1[i]);
}
如果想把里面的回复内容也显示出来(本文档仅作一个示范)
let llist = document.querySelectorAll("div.root-reply-container > div.content-warp > div.root-reply > span > span");//控制只要主评论的内容。
let text1 = [];//将评论存储为一个string数组
let text2 = [];//将id存储为一个string数组
let text3 = [];//将回复评论存储为一个stirng数组
let text4 = [];//将回复id存储为一个string数组
let namelist = document.querySelectorAll(".user-name");
let subNamelist = document.querySelectorAll(".sub-user-name");
let subLlist =document.querySelectorAll("div.sub-reply-container>div>div>span");
for(let i = 0; i<namelist.length;i++)
{
text2[i] = namelist[i].textContent;
}
for(let i = 0; i<llist.length;i++)
{
text1[i] += llist[i].innerText;
}
for(let i = 0; i<subNamelist.length;i++)
{
text3[i] = subNamelist[i].innerText;
}
for(let i = 0; i<subLlist.length;i++)
{
text4[i] = subLlist[i].innerText;
}
let j = 0;
let cnt = 0;
for(let i=0;i<namelist.length;i++)
{
console.log("id:"+text2[i]);
console.log("评论:"+text1[i]);
while(j<2)
{
console.log("id:"+text3[cnt+j]);
console.log("回复:"+text4[cnt+j]);
j++;
}
cnt +=2;
j = 0;
//console.log("\n");
}
因为B站默认显示前两条评论的回复,所以本文档直接使用数组处理,如果其他网站对于评论或是回复显示不同,可以选择不同的处理方式。
采用递归去处理应该是通用方法。