数据提取
- 数据提取就是从响应中获取想要的数据的过程
数据分类
-
非结构化数据:html等
- 处理方法:正则表达式、xpath
-
结构化数据:json、xml等
- 处理方法:转化为python数据类型
抓包
- 抓包(packet capture)就是将网络传输发送与接收的数据包进行截获、重发、编辑、转存等操作。
JSON
- JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它使得人们很容易的进行阅读和编写。同时也方便了机器进行解析和生成,适用于进行数据交互的场景,比如网页前端与后端之间的数据交互。
寻找json数据中的url
- 使用chrome切换到手机页面
- 抓包手机app的软件
json数据与python数据类型的转换
- json字符串
- json字符串使用loads()转换成python数据类型
- python数据类型使用dumps()转换成json字符串
- 包含json的类文件对象
- json类文件对象使用load()转换成python数据类型
- python数据类型使用dump()转换成json类文件对象
- 注:具有read()或者write()方法的对象就是类文件对象,即fp
pprint模块–美观打印输出
json使用注意点
-
json的字符串都是使用双引号的
- 如果不是双引号的话
- eval:能实现简单的字符串和python类型的转换
- replace:把单引号替换成双引号
- 如果不是双引号的话
-
往一个文件中写入多个json串,不再是一个json串,不能直接读取
- 一行写一个json串,按照行来读取
json类型对应的python类型
- object --> dict
- array --> list
- string --> unicode
- number(int) --> int, long
- number(real) --> float
- true --> True
- false --> False
- null --> None
正则表达式
常用的正则表达式的方法
- re.compile(编译)
- pattern.match(从开始进行匹配并返回匹配成功的第一个字符串)
- pattern.seach(匹配全文并返回匹配成功的第一个字符串)
- pattern.findall(匹配全文并返回匹配成功的所有字符串)
- pattern.sub(替换)
正则使用的注意点
re.findall("a(.*?)b",str)
,能够返回括号中的内容,括号前后的内容起到定位和过滤的效果- 原始字符串r,待匹配字符串中有反斜杠的时候,使用r能够忽略反斜杠带来的转义效果
- 点号(.)默认情况匹配不到
/n
\s
能够匹配空白字符,不仅仅匹配空格,还有\t|\r\n
XPATH和LXML类库
-
lxml是一款高性能的Python HTML/XML解析器,我们可以利用XPath来快速定位特定元素以及获取节点信息。
-
XPath(XML Path Language)是一门在HTML/XML文档中查找信息的语言,可用来在HTML/XML文档中对元素和属性进行遍历。
HTML与XML
- XML(Extensible Markup Language)可扩展标记语言
- 目的:作为传输和存储数据,其焦点是数据的内容
- HTML(HyperText Markup Language)超文本标记语言
- 目的:显示数据以及如何更好显示数据
常用节点选择工具
- Chrome插件XPath Helper
- 开源的XPath表达式编辑工具:XMLQuire(XML格式文件可用)
- Firefox插件XPath CHerker
XPath重点 *
- 使用xpath helper或者是chrome中的copy xpath都是从element中提取的数据,但是爬虫获取的是url对应的响应,往往和element不一样
- 获取文本
a/text()
获取a标签下的文本a//text()
获取a标签下的所有文本//a[text()='下一页']
选个文本为下一页的a标签
@符号
a/@href
获取a标签的href属性//ul[@id='xxx']
获取id=xxx的ul的节点
//
- 在xpath开始的时候表示从当前html中任意位置开始选择
li//a
表示的是在li标签下的所有a标签
基本语法
- 表达式:描述
- nodename:选取此节点的所有子节点
- / : 从根节点选取
- //:从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置
- . : 选取当前节点
- … : 选取当前节点的父节点
- @ : 选取属性
节点选择语法 *
-
路径表达式:描述
-
/bookstore/book[1]:选取属于bookstore子元素的第一个book元素
-
/bookstore/boo[last()]:选取属于bookstore子元素的最后一个book元素
-
/bookstore/book[last()-1]:选取属于bookstore子元素的倒数第二个元素
-
/bookstore/book[position()❤️]:选取最前面的两个属于bookstore元素的子元素的book元素
-
//title[@lang]:选取所有拥有名为lang的属性的title元素
-
//title[@lang=‘eng’]:选取所有title元素,且这些元素拥有值为eng的lang属性
-
/bookstore/book[price>35.00]:选取bookstore元素的所有book元素,且其中的price元素的值大于35.00
-
/bookstore/book[price>35.00]/title:选取bookstore元素中的book元素的所有title元素,且其中的price元素的值大于35.00
-
- :匹配任何元素节点
-
@* :匹配任何属性节点
-
node():匹配任何类型的节点
-
/bookstore/* :选取bookstore元素下的所有子元素
-
//* :选取文档中的所有元素
-
html/node()/meta/@*:选择html下面任意节点的meta节点的所有属性
-
//title[@*]:选取所有带属性的title元素
-
//book/title|//book/price:选取book元素的所有title和price元素
-
//title|//price:选取文档中的所有title和price元素
lxml库使用注意点
- lxml能够修正HTML代码,但是可能会改错
- 使用etree.tostring()观察修改之后的html,根据修改后的html字符串写xpath
- lxml能够接收bytes和str的字符串
- 提取页面数据的思路
- 先分组,取到一个包含分组标签的一个列表
- 遍历,取其中每一组进行数据的提取,这样就不会造成数据错乱