爬虫初阶(三)—— 数据处理

1.数据分类

  • 在抓取某个网站或者某个应用的内容时,内容一般分为两部分,非结构化的数据和结构化的数据。
1.1 非结构化的数据处理
  • 文本、电话号码、邮箱地址
    – 正则表达式
  • HTML 文件
    – 正则表达式
    – XPath
    – CSS选择器
1.2 结构化的数据处理
  • JSON 文件
    – JSON Path
    – 转化成Python类型进行操作(json类)
  • XML 文件
    – 转化成Python类型(xmltodict)
    – XPath
    – CSS选择器
    – 正则表达式

2.数据处理–JSON

2.1 什么是JSON
  • JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,它使得人们很容易的进行阅读和编写。同时也方便了机器进行解析和生成。适用于进行数据交互的场景,比如网站前端与后台之间的数据交互。
2.2 数据转化
2.2.1 json.loads()把json字符串转化为python字典
import requests
from pprint import pprint  # 格式化输出

url = "https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&page_limit=50&page_start=0"
html_str = requests.get(url).content.decode()

ret1 = json.loads(html_str)
pprint(ret1)
print(type(ret1))  # <class 'dict'>
2.2.2 json.dumps()把python字典转化为json字符串
ret2 = json.dumps(ret1, ensure_ascii=False, indent=2)  # 添加解码, 缩进格式化
print(ret2)
print(type(ret2))  # <class 'str'>
2.2.3 json.load()提取类文件对象中的json字符串, 转化为python字典
with open('douban.json', 'w') as f:
    f.write(json.dumps(ret2)
with open('douban.json', 'r', encoding='utf-8') as f:
    ret3 = json.load(f)
    print(ret3)
    print(type(ret3))  # <class 'dict'>
2.2.4 json.dump()能够把python字典转化为json字符串放入类文件对象中
with open('douban1.json', 'w', encoding='utf-8') as f:
    json.dump(ret1, f, ensure_ascii=False ,indent=2)

3.数据处理–XPATH和LXML类库

  • lxml是一款高性能的 Python HTML/XML 解析器,可以利用XPath,来快速的定位特定元素以及获取节点信息。
  • XPath (XML Path Language) 是一门在 HTML\XML 文档中查找信息的语言,
    可用来在 HTML\XML 文档中对元素和属性进行遍历。
3.1 XPATH节点选择语法

常用路径表达式:

表达式描述
nodename选取此节点的所有子节点
/从根节点选取
//从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置
.选取当前节点
选取当前节点的父节点
@选取属性

栗子:

路径表达式结果
bookstore选取 bookstore 元素的所有子节点
/bookstore选取根元素 bookstore。注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径
bookstore/book选取属于 bookstore 的子元素的所有 book 元素
//book选取所有 book 子元素,而不管它们在文档中的位置
bookstore//book选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置
//@lang选取名为 lang 的所有属性
/bookstore/book[1]选取属于 bookstore 子元素的第一个 book 元素
/bookstore/book[last()]选取属于 bookstore 子元素的最后一个 book 元素
/bookstore/book[last()-1]选取属于 bookstore 子元素的倒数第二个 book 元素
/bookstore/book[position() < 3]选取最前面的两个属于 bookstore 元素的子元素的 book 元素
/preceding-sibling::div[1(N)]选取前一(N)位同辈元素
/following-sibling::div[1(N)]选取后一(N)位同辈元素
//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 元素
/bookstore/book/title | //price选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素
3.2 lxml库
  1. 导入lxml 的 etree 库
  2. 利用etree.HTML,将字符串转化为Element对象
  3. Element对象具有xpath的方法
from lxml import etree

text = ''' <div> <ul> 
        <li class="item-1"><a>first item</a></li> 
        <li class="item-1"><a href="link2.html">second item</a></li> 
        <li class="item-inactive"><a href="link3.html">third item</a></li> 
        <li class="item-1"><a href="link4.html">fourth item</a></li> 
        <li class="item-0"><a href="link5.html">fifth item</a>  
        </ul> </div> '''
        
html = etree.HTML(text)
print(html)  # <Element html at 0x7f9d5c691bc8>

# 查看element对象中包含的字符串
# lxml能够修正HTML代码,但是可能会改错了,使用etree.tostring观察修改之后的html的样子,根据修改之后的html字符串写xpath
print(etree.tostring(html).decode())

# 获取class为item-1下的href
ret = html.xpath("//li[@class='item-1']/a/@href")
print(ret)

# 获取class为item-1下的文本
ret2 = html.xpath("//li[@class='item-1']/a/text()")
print(ret2)

# 每一个li是一条新闻,把url和文本组成字典
item = dict()
for href in ret:
    item["href"] = href
    item["title"] = ret2[ret.index(href)]
    print(item)

print("*"*20)
# 根据li标签进行分组, 对每一组继续写xpath
ret3 = html.xpath("//li[@class='item-1']")
print(ret3)
item2 = dict()
for i in ret3:
    item2["title"] = i.xpath("./a/text()")[0] if len(i.xpath("./a/text()"))>0 else None
    item2["href"] = i.xpath("./a/@href")[0] if len(i.xpath("./a/@href"))>0 else None
    print(item2)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值