scrapy xpath()中的/与//的区别

这两天学校的课程要求用django和scrapy写一个新闻网站,在看到//和/的时候,有点迷,就去网上查了一下,发现看的不明不白,今天我就结合自己的实践看一下他们各自的作用:

先看看网上的一些博客是怎么说的:

//a//b/@abc 指的是文档中所有a元素的属性为abc的后代b元素(包括子代元素)(多级);
//a/b/@abc 指的是文档中所有a元素的属性为abc的子代b元素(一级);
/a/b/@abc 指的是根节点b元素的属性为abc的子代b元素(一级);

看到这个我一开始是不明白的,查一查结果是这样:

子代与后代:

<div id="div1">
    <div id="div2">
        <p>hello world</p>
        <div id="div3">
            <a href="xxx.com">转到</a>
        </div>
    </div>
    <h1>你好世界</h1>
</div>

<!-- div1的后代包括div2,p,div3,a,h1 后代(多层) -->
<!-- div1的子代包括div2,h1  子代即孩子(只有一层)-->

我的爬虫爬取了国内某网站的新闻:

一开始是这样写的:

myitem = TutorialItem()
myitem['article_title'] = response.xpath("//h1[@class='main-title']/text()").extract()
myitem['article_content'] = response.xpath("//div[@class='article']/p/text()").extract()
        # 获取第一张图片,可能无图
myitem['article_image'] = response.xpath("//div[@class='img_wrapper']/img/@src").extract_first()

但是,结果不尽人意:

新闻的内容没爬到,图片链接也没有,但是往下翻翻有的网址竟然有图片链接和新闻数据

经过了近一个小时查看不同的网页的源码,发现:

有的网址是这样:

<div class="article" id="article">
			<div class="video-2017" id="videoList0" ></div>

<p>  原标题:骂小伙“<a href="https://news.sina.com.cn/s/2018-11-26/doc-ihmutuec3605595.shtml" target="_blank">这么胖还抢地铁</a>”,不带这么羞辱人的</p>
<div class="img_wrapper"><img style="max-width: 500px;" src="//n.sinaimg.cn/translate/791/w512h279/20181126/0FaG-hpevhck7479593.png" alt=""><span class="img_descr"></span></div>
<p>  “这么胖,现在这么多人还来抢地铁,回家待着去。”“自己去打个车不行吗?”“你有自知之明没有?”近日,北京天通苑北地铁站发生了一起小纠纷。早高峰期间,一小伙子不慎踩到了一个老大爷的脚。小伙子道歉之后,这位老大爷依旧不依不饶,不断训斥他。周围乘客上前拦阻,然而没什么效果。最终,该小伙被老大爷骂哭,并退出了排队通道,然后老大爷顺步而上,自己挤到前面去了。</p>
<p>  微评:胖怎么啦,吃你家饭了吗?挡你家WiFi了吗?作为一个曾经的胖子,深知他们的敏感脆弱,最看不得、听不得这种人身攻击。地铁足够宽大,容得下高矮胖瘦;而地铁也爱憎分明,不欢迎无理取闹。不得不说,这位小伙子很有教养,虽被训斥却一直在跟老大爷道歉。这位老大爷一句“自知之明”,还真说到点子上了——有些人缺的就是反求诸己。我不同意很多人拿这事重提“坏人变老”论调,“胖”不是错,“老”也不是错,但对人肆意羞辱、缺乏基本尊重,难道不值得某些人自我反思下吗?</p>
<p>  □思凝(媒体人)</p>
								 								
<p class="show_author">责任编辑:余鹏飞 </p>
				
				
</div>

有的网址是这样:

    <div class="article" id="article">
				原标题:新西兰145头领航鲸集体搁浅死亡<br />
        <div>   
<p>据新华社电 新西兰环保部26日说,在新西兰南岛南部边远海岸搁浅的145头领航鲸已全部死亡。这是今年以来新西兰海域发现的最大规模鲸群搁浅。</p>
<p>鲸群搁浅地点在南岛南端斯图尔特岛的偏远海岸,一名徒步旅行者24日夜观察到搁浅的鲸群,并向环保部报告。</p>
<p>在搁浅的领航鲸一半死亡后,由于事发地点遥远,人力机械难以到达,剩下的一半生还希望渺茫,环保部26日决定对其实施安乐死。“这是一个令人心碎的决定。”新西兰环保部官员任雷恩·莱彭斯说。</p>
<p>领航鲸在南半球海域较为常见。几乎每年新西兰海域都会发生较大规模的鲸群搁浅。去年,大约650头领航鲸在南岛北端搁浅,大部分死亡。1918年曾发生过上千头鲸搁浅死亡事件。</p>
<p>在刚刚过去的周末,新西兰各地海域集中发生了至少4起鲸搁浅事件。有专家认为,这一系列现象与本周末新西兰全境的恶劣天气或有关联。</p><p>编辑 林玮琪</p>
 <p></p> 
        </div>
					
	</div>

也就是一部分网页构成是div子代就是p满足我原先的代码(/构成的代码),但是剩下的网页不满足,所以修改一下把

 /  换成  //     :

myitem = TutorialItem()
myitem['article_title'] = response.xpath("//h1[@class='main-title']/text()").extract()
myitem['article_content'] = response.xpath("//div[@class='article']//p/text()").extract()
        # 获取第一张图片,可能无图
myitem['article_image'] = response.xpath("//div[@class='img_wrapper']//img/@src").extract_first()

结果就成功了。

#########################################

以此为证,我还觉得不够,又去实验了一波:

from lxml import etree
myhtml = """
    <body>
        <div id="div1">
            <div id="div2">
                <p>hello world</p>
                <div id="div3">
                    <a href="xxxA.com">转到A</a>
                    <a href="xxxB.com">转到B</a>
                </div>    
            </div>
            <h1>你好世界</h1>
        </div>
    </body>
    """
selector = etree.HTML(myhtml)
content1 = selector.xpath('//div[@id="div1"]/p/text()')  # 用/提取p标签的内容,提取不到 
print(content1)      # /情况下的xpath的内容
content2 = selector.xpath('//div[@id="div1"]//p/text()')  # 用//提取p标签的内容
print(content2)      # //情况下的xpath的内容
content3 = selector.xpath('//div[@id="div1"]/div[@id="div2"]/div[@id="div3"]/a/text()')  # 用/提取a标签的内容
print(content3)
content4 = selector.xpath('//div[@id="div1"]//a/text()')  # 用//提取a标签的内容
print(content4)

结果:

这个实验可以看出:

/    就类似于我们所说的绝对路径

//   是一种容错性更高的写法,可以不很具体,可以跨过很多层

所以说,爬虫可以用  //   写的,就尽量别用  /  ,提高自己代码的一些容错,指不定就会出现我自己做的时候的错误(一些网页div包着div)

这三种模式:

//a//b/@abc 指的是文档中所有a元素的属性为abc的后代b元素(包括子代元素)(多级);
//a/b/@abc 指的是文档中所有a元素的属性为abc的子代b元素(一级);
/a/b/@abc 指的是根节点b元素的属性为abc的子代b元素(一级);

通常用第一种就好了

猜你喜欢

转载自blog.csdn.net/changer_WE/article/details/84553986