目录

python爬虫系列(五)数据抽取工具学习

一、前言:

  • 现在到处都在说大数据,机器学习,深度学习。
  • 然后数据是哪里来的呢?要么你是bat这类公司,手握大量数据,一般情况下,我们都是需要通过一些必要的手段来获取数据。
  • 而说到获取数据,就离不开我们的网络爬虫,也有叫网络蜘蛛之类的等等,但本质就是一个不断从从Internt上下载数据的程序。
  • 数据下载之后是很原始的数据,此时我们接下来当然是从数据中筛选出对我们有用的数据了。
  • 此时常用的方式有使用正则、css、或者xpath等锁定目标数据并抽取出来。

二、lxml与XPath

  • Lxml 是基于libxml2库的Python封装。lxml使用C语言编写,解析速度比Beautiful Soup更快,最新版本的lxml支持CPython2.6至3.6的版本。
  • Lxml也是唯一支持解析XMl的库哦。
  • XPath即为XML路径语言,它是一种用来确定XML文档中某部分位置的语言,也就是说可以用来表示xml文档中的某个节点部分。
  • XPath基于XML的树状结构,提供在数据结构树中找寻节点的能力。而我们抓取下来的数据如果是html,此时一般我们可以先将html通过某鞋工具库转换为xml结构的数据。
  • 转换好之后当然就可以愉快的用我们的xpath语法进行数据抽取了。
  • 其实我是很喜欢xpath的,因为其编写的代码简洁,功能强大。

三、lxml学习教程

  • 本次学习我们将采用lxml库来进行操作。
  • lxml库作为python第三方库中最受欢迎的库,其底层采用C语言进行编写从而给使用者带来极好的解析速度体验。

lxml的安装

  • python3安装:pip3 install lxml

lxml.etree处理xml

  • 1、首先我们先导入etree
  • from lxml import etree

Element 类:

  • Element是ElementTree API的主要容器对象。大多数XML树功能都是通过这个类访问的。Element可以通过Element工厂轻松创建:
  • root = etree.Element(‘root’);
  • 我们你可以通过访问Element的tag属性获取元素的标签名称
  • root.tag -> root
  • Element以XML树结构进行组织数据。要创建子元素并将其添加到父元素中,可以使用append()方法:
  • root.append( etree.Element(“child1”) );
  • 我们还可以用一个更短的和更有效的方法来做到这一点:SubElement工厂。它接受与元素工厂相同的参数,但要求父节点作为第一个参数:
  • child2 = etree.SubElement(root, “child2”);
  • child3 = etree.SubElement(root, “child3”);
Elements列表
  • 我们创建的root等元素其实是一个列表累的哦
  • 我们可以这样访问创建的child2的元素名称
  • root[0].tag
  • 获取root的子元素长度
  • len(root)
  • 判断子元素的父元素
  • root is root[0].getparent();
  • 判断一个元素是否在其兄弟元素的前面
  • 我们这里的child1和child2即为兄弟元素
  • 判断root[0]是否是root[1]的前一个元素
  • root[0] is root[1].getprevious()
  • 判断root[1]是否是root[0]的后一个元素
  • root[1] is root[0].getnext()
元素携带的属性
  • 元素所携带的属性将以字典的形式进行存储,以下我们为root添加一个class属性
  • root = etree.Element(‘root’,attrib={‘class’:‘hello’});
  • 打印结果为:
  • <root class="hello"/>
  • 我们也可以在创建了元素之后添加属性:
  • root.set(‘id’,world);
  • 打印结果为:
  • <root class="hello" id="world"/>
  • 设置属性之后,我们想要读取属性也是非常容易的。
  • root.get(‘class’);
  • 输出为:hello
  • 我们可以通过keys()方法获取元素的所有属性集合,其以列表的形式返回给我们
  • root.keys();
  • 输出为:[‘class’, ‘id’]
  • 我们可以通过values()方法获取元素的所有属性对应的值的集合,其以列表的形式返回给我们
  • root.values();
  • 输出为:[‘hello’, ‘world’]
  • items()则以元组列表的形式返回所有的属性集合:
  • root.items();
  • 输出结果为:[(‘class’, ‘hello’), (‘id’, ‘world’)]
  • 元素的attrib属性负责存储我们的属性集合,我们也可以直接取出来进行设置
  • at = root.attrib;
  • at[‘class’]=‘hello’;
  • root.set(‘class’,‘hello’)两者是等价的

Text

  • 元素的text属性存储了元素的内容。
  • 如我们需要在创建<title>hello</title>
  • root = etree.Element(“root”);
  • root.text=‘hello’;
  • print(etree.tostring(root,pretty_print=True))
  • 输出为:<title>hello</title>
  • 以上也部分证明了root其实是一个列表哦。

xpath抽取内容

  • 我们可以使用元素自身提供的xpath去获取title内部的内容,结果以列表的形式返回
  • root.xpath(’//title/text()’);
  • 输出为:[‘hello’]
  • 我们还可以判断获取的内容是不是text
  • text = root.xpath(’//text()’);
  • print(text[0].is_text)
  • 输出内容为:True

元素的迭代

  • 我们有时候希望遍历整个文档的内容,for in语句当然是我们最常用的了。
  • lxml的元素本身也提供了迭代的能力
  • root = etree.Element(“root”)
  • etree.SubElement(root, “child”).text = “Child 1”
  • etree.SubElement(root, “child”).text = “Child 2”
  • etree.SubElement(root, “another”).text = “Child 3”
  • for element in root.iter():print("%s - %s" % (element.tag, element.text))
  • 结果输出为 root - None child - Child 1 child - Child 2 another - Child 3

fromstring() 、 XML()、HTML()

  • 我们解析的文本有可能是一个本地文件,也有可能是网上请求的一个string,一般我们可以使用fromstring()和XML()两个方法来加载需要解析的数据。
  • 当然,一般如果你是用在爬虫项目中,可能更多的就是使用HTML()方法了

xpath进阶学习

  • OK,我们根据上面的示例代码,通过从中获取div、ul、li等标签来学习xpath的使用技巧。
  • 获取div标签
  • div_tag = root.xpath(’//div’)
  • print(div_tag)
  • 打印输出为:[<Element div at 0x10b681f88>]
  • 获取ul标签
  • ul_tag = root.xpath(’//div/ul’)
  • print(ul_tag)
  • 打印输出为:[<Element ul at 0x10bdfde48>]
  • 获取li标签:
  • li_tag = root.xpath(’//div/ul/li’)
  • print(li_tag)
  • [<Element li at 0x10bdfdd48>, <Element li at 0x10bdfdec8>, <Element li at 0x10bdfdf08>, <Element li at 0x10bdfdf48>]
  • 从上面三个示例可以看到,其返回结果为我们xpath表达式定位的标签列表。

  • 返回的数据均为Element元素,这样保证了我们的抽取结果可以继续使用Element类的能力,你可以通过Elementapi继续抽取数据,也可以继续通过xpath继续抽取数据。

  • 我们也可以直接获取带某个属性的元素集合:

  • class_tag = root.xpath(’//@class’)
  • print(class_tag)
  • 结果输出为:[‘item-0’, ‘item-1’, ‘item-2’, ‘item-3’]
  • 如此我们便获取了带class属性的值集合。

  • 我们来获取class=“item-0"下面的a标签

  • li1 = root.xpath(’//div/ul/li[@class=“item-0”]/a’);
  • print(li1)
  • [<Element a at 0x10c4a1048>]
  • 当然,我们也可以换个方式,我们获取href=“link1.html"的a标签
  • li1 = root.xpath(’//li/a[@href=“link1.html”]’);
  • print(li1)
  • [<Element a at 0x10f5aa048>]
  • 获取最后一个li标签里面的a标签的href属性的值
  • href_value = root.xpath(’//li[last()]/a/@href’);
  • print(href_value)
  • [’link4.html’]