Xpath
Xpath
Xpath在Pycharm中运行
Xpath默认是通过命令行进行运行的,我们可以采用下面方法进行修改,从而能够直接在pycharm中设置断点,从而进行Debug
-
在项目下创建一个begin.py文件
image
-
在begin.py中填写代码
from scrapy import cmdline
cmdline.execute('scrapy crawl douban -o douban.csv'.split())
其中''内为命令行执行语句
-
修改配置
image
Xpath解析问题猜的坑
Xpath语法中的/、//起初真的让人搞的头痛,下面记录一下爬取中国大学排名时出现的错误。
image
我们可以看出需要爬取的内容全部在class为hidden_zhpm中的tbody中,每一个大学的信息都是一个名为alt xh-highlight的tr,我的思路是从页面中先获取整个tbody,我编写的代码为:
node_list=response.xpath("//tbody[@class='hidden_zhpm']/tr")
这行代码是没有问题的,问题出现在我处理每一个tr标签的时候:
for node in node_list:
rank=node.xpath("//tr[@class='alt']/td[0]").extract()[0]
print(rank)
我在测试是否爬取排名正确的时候,使用这段代码测试,发现输出的全部为1,也就是排名没有改变;然后我将node.xpath("//tr[@class='tr']/td[0]").extract()输出后发现是一个list,里面有所有大学的排名,这也就可以解释为什么我[0]时输出的一直是1.
那么问题来了,为什么我获取的是所有大学的排名,而我只想获取每个tr标签下的排名信息,原因出现在第二次的xpath中.
item['rank']=node.xpath("./td[1]/text()").extract()[0]
我使用//进行匹配,但是这个是从根节点进行匹配,匹配根节点下所有名为alt的tr,也就是说所有大学的信息都被匹配出来了,这时候我获取td[0]就将所有大学的排名选了出来,所以extract()后的内容是一个包含所有大学排名的list,如果想从每个tr标签下筛选内容应该使用:./
item['rank']=node.xpath("./td[1]/text()").extract()[0]
.表示从node开始的路径继续选取,所以每个node下就只能筛选出当前node的排名。
这个bug我改了很久,原因还是对Xpath语法不熟悉,在和学长讨论后我觉得他的解释很清晰,这里拿来看一下:
类似linux:
//是当前文档匹配所有后序表达的意思
单独的/是指根目录
.表示当前结点
在for循环中,每个node是一个selector,当使用./时是在当前selector下开始搜索,而使用//时是在当前文档中进行搜索,而不是从当前节点向下搜索
另外经过观察,我觉得/和//的区别是:
-
a/name:只会匹配a的name孩子节点,不包括子孙节点 -
a//name:会匹配a下的所有name的节点,包括孩子节点和子孙节点