从网页中提取特征量

本文主要介绍了Scrapy常用的数据提取的方法,包括seletors、scrapy shell、xpath、css、BeautifulSoup的使用方法及案例。只要掌握xpath或者css任意一种即可。

 

1、seletors选择器

1)介绍

        Scrapy提取数据有自己的一套机制。它们被称作选择器(seletors),构建于lxml库之上,通过特定的XPath或者CSS表达式来等“选择” HTML文件中的某个部分。Selector有四个基本的方法,最常用的还是xpath:

  • XPath(query):传入Xpath表达式queery,返回该表达式对应的所有节点的selector list。Xpath是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历。

  • css(query):传入css表达式query,返回该表达式所对应的所有节点的selector list列表CSS是将HTML文档样式化的语言。选择器由它定义,并与特定的HTML元素的样式相关联。

  • re(): 根据传入的正则表达式对数据进行提取,返回Unicode字符串list列表

  • extract(): 序列化该节点为Unicode字符串并返回list

 

2)导入seletors

from scrapy.selector import Selector, HtmlXPathSelector

from scrapy.http import HtmlResponse

 

3)常用xpath使用方法:

 

常用语法:

  • /:根节点

  • //xxx/zzz:路径

  • //div:去全局的子孙中找所有的div元素

  • .//表示去当前对象的子孙中找

  • /xxx//div:去儿子对象中找xxx节点下所有的div元素

  • *:匹配任意节点元素

  • /html/body/div[1]:选取body下的第一个div节点

  • //div[@class="xxx"]:选取class属性为xxx的div节点

  • //@attr:获取attr对应的值

常用函数:

  • text():提取文本信息,//*[@class='xxx']/text()

  • position():选取第几个节点,//*[position()=1]

  • last():选取最后一个节点,//*[last()]

  • starts-with(@attr,substr):attr属性值开头substr的节点

  • contains(@attr,substr):attr属性值是否包含substr

运算符:

  • |:计算两个节点集合,比如//div|//li

  • 比较运算符=,!=,<=...,比如//price[text()>10]

  • 算数运算符:+,-,*,div,比如//price[text()+1]

  • 逻辑运算符:or,and,[@class='xxxx' or @class='yyyy']

     

     

     

 

4)xpath语法案例:以取a标签为案例,div、span等都相同

 

  • xpath('//a'):找到全局中所有的a标签

  • xpath('//a/text()  '):获取a标签的文本值

  • xpath('//a/span'):a标签对象儿子下的span标签

  • xpath('//a[2]'):a标签找到后,返回的是一个列表,[n]列表的n位置的值

  • xpath('//a[@id]'):找全局中属性为id的a标签

  • xpath('//a[@id="i1"]'):找全局中属性id为i1的a标签

  • xpath('//a/@id'):取a标签的id的属性值

  • xpath('//a[@href="link.html"][@id="i1"]'):两个[]代表双条件,需要href="link.html“,且id="i1"的a标签

  • xpath('//a[contains(@href, "link")]'):a标签的href需要包含"link"字符

  • xpath('//a[starts-with(@href, "link")]'):a标签的href需要以"link"开头

  • xpath('//a[re:test(@id, "i\d+")]'):正则表达式的写法,需要有re:test

  • xpath('//a[re:test(@id, "i\d+")]/@href').extract(),正则表达式的写法案例

  • xpath(.//)在当前基础上往下找,需要加“.”,比如用在for循环中

  • obj.extract()#列表中的每一个对象转化字符串==>返回一个列表

  • obj.extract_first() #列表中的每一个对象转化字符==>列表中的第一个元素

  • xpath('/html/body/ul/li/a/@href').extract():一层层去找标签

 

5)获取代码,需要在页面,右键-----检查元素---去看下html结构。

也可以直接选择自己想要的内容,通过copy---copy xpath直接获得源代码,去粘贴即可。

比如选取下面页面的肖申克救赎的信息:但一般这种路径都会特别长。

//*[@id="content"]/div/div[1]/ol/li[1]/div/div[2]/div[1]/a/span[1]

640?wx_fmt=png

 

6)css语法

基本语法:

  • .classvalue:选择class属性为classvalue的元素

  • #idvalue:选择id值为idvalue的元素

  • p:选择所有的p元素

  • div,p:选择所有的div和p元素

  • div~p:前面有div元素的每个p元素,div和p为兄弟节点

  • li span :选择li内部所有的span元素

  • div>p:选择父结点为div的所有p元素

  • ::text/::attr(src):文本信息/提取某个属性的值,比如a::attr(href),提取超链接

     

属性的语法:

  • [attr]选择所有带attr属性的元素

  • [attr=val]选择attr值为val的所有元素:[numvalue=num1]

  • [attr^=val]选择attr属性值以val开头的元素:[src^=http]

  • [attr$=val]选择attr属性值以val结尾的元素:[src^=.jpg]

  • [attr*=val]选择attr属性值包含val的元素:[src*=douban]

     

ele语法:

  • ele:first-of-type:所有子元素为ele的第一个元素

  • ele:first-child:第一个元素为ele的元素

  • ele:only-of-type:类型为ele的元素

  • ele:only-child:唯一子元素的每个ele元素

  • ele:nth-of-type(n):选择第n个ele元素

  • ele:nth-child(n):第n个子元素为ele的元素

  • ele:last-child:最后一个为ele的子元素

 

 

2、Scrapy shell交互,测试网页代码

    Scrapy终端是一个交互终端shell,我们可以在未启动spider的情况下尝试及调试代码,也可以用来测试XPath或CSS表达式,查看他们的工作方式,方便我们爬取的网页中提取的数据。一旦你习惯使用了Scrapy shell,你将会发现Scrapy shell对于开发爬虫是非常好用的一个测试工具。

1)启动Scrapy shell,有三种方式请求url

1-1直接请求url:

    首先需要cmd-----进入项目根目录,然后填写"scrapy shell +url(你需要访问的页面地址) ",如下所示,即可返回信息。

 

640?wx_fmt=png

会看到如下的信息

640?wx_fmt=png

比如输入:response.xpath('//title')可以看到如下信息:

640?wx_fmt=png

    Scrapy Shell根据下载的页面会自动创建一些方便使用的对象,例如Response对象,以及Selector对象(对HTML及XML内容)。当shell载入后,将得到一个包含response数据的本地 response 变量。

  • 输入response.body将输出response的包体。

  • 输入response.headers可以看到response的包头。

  • 输入response.selector时,将获取到一个response初始化的类Selector的对象,此时可以通过使用response.selector.xpath()或response.selector.css()来对response进行查询。

  • Scrapy也提供了一些快捷方式, 例如 response.xpath()或response.css()同样可以生效。


1-2请求url设置请求信息,使用:scrapy shell -s name=value语句

比如直接设置代理USER_AGENT的语句:

640?wx_fmt=png

1-3 在命令行直接请求url,利用fetch。

req=Request(url,header={})

r=fetch(url)

 

640?wx_fmt=png

然后就可以看到response.url的信息了。

 

 

2)测试xpath的使用语法:以豆瓣TOP250为例。

  • 比如选取html:response.xpath('/html')

640?wx_fmt=png

  • 提取网页的title:response.xpath('/html/head/title')

 

640?wx_fmt=png

  • 找到所有的a标签,或找到body下所有的a标签:response.xpath('//body//a')

640?wx_fmt=png

640?wx_fmt=png

  • 找到body下所有的标签

640?wx_fmt=png

  • text()获取电影名称:response.xpath('//div[@class="hd"]//a/span[1]/text()').extract()640?wx_fmt=png

640?wx_fmt=png

  • 获取所有的电影的连接:response.xpath('//div[@class="hd"]//a/@href').extract()

640?wx_fmt=png

  • 提取所有的电影评分:response.xpath('//span[@class="rating_num"]/text()').extract()

 

640?wx_fmt=png

  • 提取所有的电影评分,且限制评分。response.xpath('//span[@class="rating_num" and text()>9.4]/text()').extract()

640?wx_fmt=png

  • 提取页码:response.xpath('//span[@class="next"]//a/@href').extract()

640?wx_fmt=png

 

 

3)测试CSS的使用案例:以豆瓣TOP250为例。

  • 比如选取html:response.css('html')

 

640?wx_fmt=png

  • 提取网页的title:response.css('html head title')

 

640?wx_fmt=png

 

  • 获取body下所有的a :response.css('body a')

640?wx_fmt=png

  • text()获取所有的电影名称:response.css('.title::text')

 

640?wx_fmt=png

根据文档结构,可以写成如下格式:response.css('.title::text')

640?wx_fmt=png

  • 也可以使用ele语法获取电影名称:response.css("[class='hd'] a span:first-of-type").extract()

640?wx_fmt=png

  • 获取所有的电影的连接:response.css('.hd a::attr(href)').extract()

 

640?wx_fmt=png

  • 提取所有的电影的评分:response.css('.rating_num::text').extract()

640?wx_fmt=png

  • 提取图片:response.css("[src$=jpg]").extract()

 

640?wx_fmt=png

 

 

附录::

 

附1、BeautifulSoup

    BeautifulSoup是一个模块,该模块用于接收一个HTML或XML字符串,然后将其进行格式化,之后就可以使用他提供的方法进行快速查找指定元素,从而使得在HTML或XML中查找指定元素变得简单。

四大对象种类

Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种:

  •     Tag:HTML 中的一个个标签,比如a,div等,有两个属性name和attrs

  •     NavigableString:标签内部的文字,可以用 .string获得

  •     BeautifulSoup:表示的是一个文档的全部内容

  •     Comment:注释

 

1)模块的安装(需要cmd,进入到python的工作目录)

    pip3 install beautifulsoup4

 

2)导入模块

    from bs4 import BeautifulSoup

3)创建对象

    soup=BeautifulSoup(response.text,'html.parser')

 

4)使用语法:

  • soup.find('a'):获取匹配的第一个a标签,a可以改成span、div等

  • soup.find_all('a'):获取所有匹配的a标签,是列表形式

  • soup.find_all(id='xx'):查找属性id为xx的所有节点

  • soup.find_all(div,class_='xx'):查找class属性为xx的所有div节点

  • soup.find_all(a,text='xx'):查找text值为xx的所有a节点

  • soup.find_all(a,text=re.complite('xx')):正则查找text值为xx的所有a节点

  • soup.find('a').has_attr('id'),其中has_attr,检查标签是否具有该属性

  • soup.find('body').children:找到所有子标签

  • soup.find('body').descendants:找到所有的子子孙孙标签

  • soup.find('body').clear(),将标签的所有子标签全部清空(保留标签名)

  • soup.find('body').decompose():decompose,递归的删除所有的标签

  • soup.find('body')..extract():解析标签

  • soup.find('body').decode(),soup.find('body').decode_contents(),decode,转换为字符串(含当前标签);decode_contents(不含当前标签)

  • soup.find_all('a',limit=1),只拿第一个a标签

  • soup.find_all(name='a', attrs={'class': 'sister'}, recursive=True, text='Lacie')限制属性;等同于soup.find(name='a', class_='sister', recursive=True, text='Lacie');recursive=True代表查找所有的节点,recursive=False代表只查找本节点下的东西

  • soup.find_all(name=['a','div']),限制选取全部的a、div标签

  • soup.find_all(href=['link1','link2']),选取href为link11、link2的标签

  • soup.find_all(text=['Tillie']),text为Tillie的所有节点

  • soup.find_all(class_=['sister0', 'sister']),限制class=sister0、sister

  • 正则表达式rep = re.compile('sister.*') ,v = soup.find_all(class_=rep)

  • soup.find('a').get_text,其中get_text获取标签内部文本内容 

  • soup.find('br').is_empty_element,其中is_empty_element,是否是空标签(是否可以是空)或者自闭合标签,判断是否是如下标签:'br' , 'hr', 'input', 'img', 'meta','spacer', 'link', 'frame'。

  • soup.strings,获取多个标签内容

  • list(soup.stripped_strings),可以去除多余空白内容

  • append在当前标签内部追加一个标签

 

5)使用soup.select()通过css进行筛选:

可参考css部分知识,仅举部分案例

  • soup.select('a'):获取匹配的a标签

  • soup.select('div a'):按层级获取div下的a标签

  • soup.select('.css1'):查找属性值为css1的标签

  • soup.select('#id1'):查找id属性值为#id1的标签

  • soup.select('div[class]'):查找存在某个属性值的标签

  • soup.select('div>p'):选择父结点为div的所有p元素

  • soup.select('div~p'):前面有div元素的每个p元素,div和p为兄弟节点

  • soup.select('attr^=val'):属性attr以val开头的标签

 

具体可参考:

http://www.cnblogs.com/wupeiqi/articles/6283017.html

 

5)使用案例:

from bs4 import BeautifulSoup

html_doc = """

<html><head><title>The Dormouse's story</title></head>
<body>
asdf
   <div class="title">
       <b>The Dormouse's story总共</b>
       <h1>f</h1>
   </div>

<div class="story">Once upon a time there were three little sisters; and their names were
   <a class="sister0" id="link1">Els<span>f</span>ie</a>,
   <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
   <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</div>
ad<br/>sf
<p class="story">...</p>
</body>
</html>

"""
#封装使用案例:
soup = BeautifulSoup(html_doc, features="lxml")
tag1 = soup.find(name='a')
print('找到第一个a标签',tag1)
tag2 = soup.find_all(name='a')
print('找到所有的a标签',tag2)
tag3 = soup.select('#link2')
print('找到id=link2的标签',tag3)

执行效果:

640?wx_fmt=png

 

 

附2、XPath

    XPath 是一门在 XML 文档中查找信息的语言。XPath用于在 XML文档中通过元素和属性进行导航。

 

1、节点介绍:

    在 XPath 中,有七种类型的节点:元素、属性、文本、命名空间、处理指令、注释以及文档节点(或称为根节点)。

如下例:

 

640?wx_fmt=png

上面的XML文档中的节点例子:

<bookstore> (文档节点) 

<author>J K. Rowling</author> (元素节点) 

lang="en" (属性节点)

 

2、节点关系:

  • 父(Parent):每个元素以及属性都有一个父。

在下面的例子中,book 元素是 title、author、year 以及 price 元素的父:

  • 子(Children):元素节点可有零个、一个或多个子。

在下面的例子中,title、author、year 以及 price 元素都是 book 元素的子:

  • 同胞(Sibling):拥有相同的父的节点

在下面的例子中,title、author、year 以及 price 元素都是同胞:

 

  • 先辈(Ancestor):某节点的父、父的父,等等。

在下面的例子中,title 元素的先辈是 book 元素和 bookstore 元素:

  • 后代(Descendant):某个节点的子,子的子,等等。

在下面的例子中,bookstore 的后代是 book、title、author、year 以及 price 元素:

 

3、XPath 语法

 

1)常用表达式:640?wx_fmt=png

640?wx_fmt=png

以下例看使用案例:

640?wx_fmt=png

  • xpath(‘bookstore’) 选取 bookstore元素的所有子节点。

  • xpath(‘/bookstore’),选取根元素

  • xpath(‘bookstore/book’),选取属于 bookstore 的子元素的所有 book 元素。

  • xpath(‘//book’),全局中找到所有的book元素,而不管它们在文档中的位置。 

  • xpath(‘bookstore//book’) 选择属于bookstore元素的后代的所有 book 元素,而不管它们位于bookstore之下的什么位置。 

  • xpath(‘//@lang’)  选取名为 lang 的所有属性。  

  • xpath(‘ /bookstore/*’) 选取 bookstore 元素的所有子元素。 

  • xpath(‘ //*’) 选取文档中的所有元素。 

  • xpath(‘ //title[@*]’) 选取所有带有属性的 title 元素。 

 

通过在路径表达式中使用“|”运算符,您可以选取若干个路径。

  • //book/title | //book/price 选取 book 元素的所有 title 和 price 元素。 

  • //title | //price 选取文档中的所有 title 和 price 元素。 

  • /bookstore/book/title | //price 选取属于 bookstore元素的book元素的所有title元素,以及文档中所有的price元素。 

2)谓语

    谓语用来查找某个特定的节点或者包含某个指定的值的节点。谓语被嵌在方括号中。

比如以下用法:

 

640?wx_fmt=png

posted @ 2018-08-22 23:47  asges林  阅读(968)  评论(0编辑  收藏  举报