在Scrapy中如何利用Xpath选择器从HTML中提取目标信息(两种方式)

前一阵子我们介绍了如何启动Scrapy项目以及关于Scrapy爬虫的一些小技巧介绍,没来得及上车的小伙伴可以戳这些文章:

手把手教你如何新建scrapy爬虫框架的第一个项目(上)

手把手教你如何新建scrapy爬虫框架的第一个项目(下)

关于Scrapy爬虫项目运行和调试的小技巧(上篇)

关于Scrapy爬虫项目运行和调试的小技巧(下篇)

今天我们将介绍在Scrapy中如何利用Xpath选择器从HTML中提取目标信息。在Scrapy中,其提供了两种数据提取的方式,一种是Xpath选择器,一种是CSS选择器,这一讲我们先聚焦Xpath选择器,仍然是以伯乐在线网为示例网站。

1、 打开网站,然后随机选择任意一篇文章进行查看,如下图所示。

我们需要提取的信息主要有标题、日期、主题、评论数、正文等等。

2、接下来我们就可以开始写代码了,基础代码如下图所示,需要注意的是start_urls参数值改为了具体的URL,其他的代码未发生改变。

3、回到原始网页,按下键盘的快捷键F12或者在网页上点击鼠标右键,然后选择“检查(N)”弹出网页的调试界面,如下图所示。

4、点击下图中红色框框的小图标,可以实现网页数据和源码之间的交互,可以很方便的帮助我们定位标签。

5、如下图所示,当我们选择上图中的小图标之后,再选择网页上的标题,尔后网页源码会自动跳转到我们定位的部分,可以看到标题在

标签下。

6、尔后我们就可以根据上图中的网页层次结构写出标题的Xpath表达式,这里先提供一种比较笨的方法,从头到尾进行罗列的写,“/html/body/div[1]/div[3]/div[1]/div[1]/h1”,有没有发现灰常的辛苦,像这种大标题信息还比较好提取一些,若是碰到犄角旮旯的信息,就比较难写表达式了,而且这种方式容易出错,效率还低。不过小伙伴们不用灰心,浏览器给我们提供了一个便捷的方式,让我们可以直接复制Xpath表达式。在标题处或者目标信息处右键,然后选择“Copy”,再选择“Copy Xpath”即可进行复制该标签的Xpath表达式,具体过程如下图所示。

可以看到复制的Xpath表达式为“//*[@id="post-113659"]/div[1]/h1”,其中id="post-113659"是属于这篇文章的一个标识,如下图所示。

通过该标识我们就可以很快的定位到标签,其与我们用笨方法手动写出来的Xpath表达式有时候并不是一致的。下面将两个Xpath表达式所匹配的内容分别进行输出。

7、将Xpath表达式写入Scrapy爬虫主体文件中,尔后Debug我们之前定义的main.py文件,将会得到下图的输出。可以看到selector1和selector2中的数据即是网页上的内容,而且内容是一致的。

之后点击停止Debug模式,便可以退出Debug模式。

8、从上图中我们可以看到选择器将标签

也都取出来了,而我们想要取的内容仅仅是标签内部的数据,此时只需要使用在Xpath表达式后边加入text()函数,便可以将其中的数据进行取出。

通过这篇文章,我们可以了解到尽管我们自己写出的Xpath表达式和浏览器给我们返回的Xpath表达式在写法上并不一致,但是程序运行之后,其返回的数据内容是一致的。换句话说,关于某个目标数据的Xpath表达式并不是唯一的,只要符合Xpath表达式语法,即便是写的很短,也是没问题的,你开心就好。此外在Scrapy爬虫框架中,text()函数常常与Xpath表达式运用在一块,用于提取节点中的数据内容。

原文地址:https://www.cnblogs.com/dcpeng/p/10990499.html

时间: 2024-08-26 01:01:08

在Scrapy中如何利用Xpath选择器从HTML中提取目标信息(两种方式)的相关文章

SpringBoot中使用Spring Data Jpa 实现简单的动态查询的两种方法

首先谢谢大佬的简书文章:http://www.jianshu.com/p/45ad65690e33# 这篇文章中讲的是spring中使用spring data jpa,使用了xml配置文件.我现在使用的是spring boot ,没有了xml文件配置就方便多了.我同样尝试了两种方式,也都是简单的查询,需要更复杂的查询,还需要我研究研究.往下看,需要先配置springboot的开发环境,需要大致了解springboot,这里可以看下面两篇文章: springboot 项目新建 springboot

【REACT NATIVE 系列教程之十三】利用LISTVIEW与TEXTINPUT制作聊天/对话框&&获取组件实例常用的两种方式

本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/react-native/2346.html 本篇Himi来利用ListView和TextInput这两种组件实现对话.聊天框. 首先需要准备的有几点:(组件的学习就不赘述了,简单且官方有文档) 1. 学习下 ListView: 官方示例:http://reactnative.cn/docs/0.27/tutorial.html#content

在基于MVC的Web项目中使用Web API和直接连接两种方式混合式接入

在我之前介绍的混合式开发框架中,其界面是基于Winform的实现方式,后台使用Web API.WCF服务以及直接连接数据库的几种方式混合式接入,在Web项目中我们也可以采用这种方式实现混合式的接入方式,虽然Web API或者WCF方式的调用,相对直接连接数据库方式,响应效率上略差一些,不过扩展性强,也可以调动更多的设备接入,包括移动应用接入,网站接入,Winfrom客户端接入,这样可以使得服务逻辑相对独立,负责提供接口即可.这种方式中最有代表性的就是当前Web API的广泛应用,促进了各个接入端

简述java中抛出异常的两种方式

java编程中经常遇到异常,这时就需要利用java中的异常抛出机制,在java中提供了两种抛出异常的方法:try{}  catch() {}和throw. 一.抛出异常的两种方式 (1) 首先我们来看一下try()  catch(){}这种方式: ? 1 2 3 4 5 6 try{    i=9\0; } catch(exception e) {     system.out.println("除数不能为0"): } 该种方式是将待执行的代码放入try中,如果执行的代码发生异常就会被

strus2中获取表单数据 两种方式 属性驱动 和模型驱动

strus2中获取表单数据 两种方式 属性驱动 和模型驱动 属性驱动 /** * 当前请求的action在栈顶,ss是栈顶的元素,所以可以利用setValue方法赋值* 如果一个属性在对象栈,在页面上可以根据name属性进行回显*/ /** * 属性驱动实现的条件:* 1.当前请求的action在栈顶,所以action中的属性就暴漏出来了* 2.获取页面上表单的元素,整合成一个map * 3.调用setValue方法赋值*/ 1 package cn.itcast.struts2.sh; 2 3

iOS中创建单例的两种方式

刚刚开始做iOS开发的时候,不知道怎么创建单例,在网上搜的也大多数都不太全,所以总结了一下创建单例的两种方式 首先在.h文件中声明类方法 1 +(instancetype)sharedUtils; 然后在.m文件中实现它,实现的方法有两种 第一种,在创建一个对象时先判断在程序中有没有创建过这个对象 1 static PublicUtils *DefaultManager = nil; 2 3 +(instancetype)sharedUtils 4 { 5 if (!DefaultManager

旧文备份:利用一个定时器实现多个虚拟定时器的两种方法

固定周期法 使用一个硬件定时器进行固定周期(比如1ms)定时,用一个结构体数组作为软定时器描述表,数组的结构体数就是最大虚拟定时器的数量,每个结构体的成员都包括虚拟定时器状态(空闲.激活.运行.超时触发.周期触发).定时值(换算成定时周期数,例如1ms的硬件定时周期,现进行125ms的定时,定时值就是125).标识ID和回调函数等:用一个变量作为定时周期计数器,每次进入定时中断,重置定时器,扫描结构体数组中的每个成员结构体,对定时值做减一操作,然后判断该定时值是否为0,是则判定该值对应的虚拟定时

述java中抛出异常的两种方式

java编程中经常遇到异常,这时就需要利用java中的异常抛出机制,在java中提供了两种抛出异常的方法:try{}  catch() {}和throw. 一.抛出异常的两种方式 (1) 首先我们来看一下try()  catch(){}这种方式: ? 1 2 3 4 5 6 try{    i=9\0; } catch(exception e) {     system.out.println("除数不能为0"): } 该种方式是将待执行的代码放入try中,如果执行的代码发生异常就会被

Java中实现多线程的两种方式之间的区别

Java提供了线程类Thread来创建多线程的程序.其实,创建线程与创建普通的类的对象的操作是一样的,而线程就是Thread类或其子类的实例对象.每个Thread对象描述了一个单独的线程.要产生一个线程,有两种方法: ◆需要从Java.lang.Thread类派生一个新的线程类,重载它的run()方法:  ◆实现Runnalbe接口,重载Runnalbe接口中的run()方法. 为什么Java要提供两种方法来创建线程呢?它们都有哪些区别?相比而言,哪一种方法更好呢? 在Java中,类仅支持单继承