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’]