在爬虫爬取的数据中有很多不同类型的数据,我们需要了解数据的不同类型来又规律的提取和解析数据.
<bookstore>
<book category="COOKING">
<title lang="en">Everyday Italiantitle>
<author>Giada De Laurentiisauthor>
<year>2005year>
<price>30.00price>
book>
<book category="CHILDREN">
<title lang="en">Harry Pottertitle>
<author>J K. Rowlingauthor>
<year>2005year>
<price>29.99price>
book>
<book category="WEB">
<title lang="en">Learning XMLtitle>
<author>Erik T. Rayauthor>
<year>2003year>
<price>39.95price>
book>
bookstore>
然后用 json.loads() 转化为列表或者字典 , 然后进行需要的数据解析提取,随后将提取的数据,再封装成字典或者列表,随后可以通过 json.dumps() 方法转化为字符串通过文件进行保存, 或者根据需要存入数据库中。
用来解析多层嵌套的json数据;JsonPath 是一种信息抽取类库,是从JSON文档中抽取指定信息的工具,提供多种语言实现版本,包括:Javascript, Python, PHP 和 Java。
pip install jsonpath # 安装
官方文档:http://goessner.net/articles/JsonPath
JSONPath 语法:
{ "store": {
"book": [
{ "category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{ "category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{ "category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{ "category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
}
}
JSONPath | Result |
---|---|
$.store.book[*].author |
store中的所有的book的作者 |
$..author |
所有的作者 |
$.store.* |
store下的所有的元素 |
$.store..price |
store中的所有的内容的价格 |
$..book[2] |
第三本书 |
$..book[(@.length-1)] |
$..book[-1:] |
$..book[0,1] |
$..book[:2] |
$..book[?(@.isbn)] |
获取有isbn的所有数 |
$..book[?(@.price<10)] |
获取价格大于10的所有的书 |
$..* |
获取所有的数据 |
目标URL: https://www.lagou.com/lbs/getAllCitySearchLabels.json
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2020/8/15 14:54
# @Author : GHong
import requests
import jsonpath
from json import loads
url = "https://www.lagou.com/lbs/getAllCitySearchLabels.json"
headers = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36"
}
response = requests.get(url, headers=headers)
data_dict = loads(response.content.decode()) # 转换成字典类型
# 通过结构分析我们想要获取所有城市的名称
# 这个数据在content=>data=>allCitySearchLabels=>A,B,C,D,E,F...=>[]["name"]
"""
方案一:不使用JsonPath 模块
"""
# node = data_dict["content"]["data"]["allCitySearchLabels"]
#
# upper = list(map(chr, range(65, 91))) # 快速生成大写字母表
#
# for i in upper:
# try:
# for item in node[i]:
# print(item["name"])
# except:
# print("没有以%s开头的城市" % i)
"""使用Jsonpath模块"""
for item in jsonpath.jsonpath(data_dict, "$..name"):
print(item)
爬取豆瓣上所有的 (国产剧,英美剧,动漫,韩剧,日剧,综艺的 【片名,评分及链接】)
参考答案 提取码:b8ml
用事先定义好的一些特定字符、及这些特定字符的组合,组成一个规则字符串,这个规则字符串用来表达对字符串的一种过滤逻辑。
知识点
pattern.match(从头找一个)
pattern.search(找一个)
pattern.findall(找所有)
re.findall("\d","chuan1zhi2") >> ["1","2"]
pattern.sub(替换)
re.sub("\d","_","chuan1zhi2") >> ["chuan_zhi_"]
re.compile(编译)
返回一个模型P,具有和re一样的方法,但是传递的参数不同
匹配模式需要传到compile中
p = re.compile("\d",re.S)
p.findall("chuan1zhi2")
在某些情况下,我们想匹配文本中的汉字,有一点需要注意的是,中文的 unicode 编码范围 主要在 [u4e00-u9fa5],这里说主要是因为这个范围并不完整,比如没有包括全角(中文)标点,不过,在大部分情况下,应该是够用的。
import re
str = "你好呀,ha杀ki"
print(re.findall(r'[\u4e00-\u9fa5]+', str))
目标URL:http://www.chinanews.com/
import re
import requests
url = "http://www.chinanews.com/"
response = requests.get(url)
# print(response.content.decode())
txt = response.content.decode()
# 通过观察我们发现目标数据结构 :
"""
"""
nodes = re.findall(r'
, txt)
for node in nodes:
print(url + node)
lxml是一款高性能的 Python HTML/XML 解析器,我们可以利用XPath,来快速的定位特定元素以及获取节点信息
XPath (XML Path Language) 是一门在 HTML\XML 文档中查找信息的语言,可用来在 HTML\XML 文档中对元素和属性进行遍历。
W3School官方文档:http://www.w3school.com.cn/xpath/index.asp
xml使用一系列简单的标记描述数据,而这些标记可以用方便的方式建立,虽然可扩展标记语言占用的空间比二进制数据要占用更多的空间,但可扩展标记语言极其简单易于掌握和使用。
知识点:
每个XML的标签我们都称之为节点,其中最顶层的节点称为根节点。
注意: 这些工具是用来学习xpath语法的,他们都是从elements中匹配数据,elements中的数据和url地址对应的响应不相同,所以在代码中,不建议使用这些工具进行数据的提取
Xpath Helper 快捷键 ctrl + shift +alt +x 【激活Xpath窗口】
XPath 使用路径表达式来选取 XML 文档中的节点或者节点集。这些路径表达式和我们在常规的电脑文件系统中看到的表达式非常相似。
使用chrome插件选择标签时候,选中时,选中的标签会添加属性class="xh-highlight"
表达式 | 描述 |
---|---|
nodename | 选中该元素。 |
/ | 从根节点选取、或者是元素和元素间的过渡。 |
// | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。 |
. | 选取当前节点。 |
… | 选取当前节点的父节点。 |
@ | 选取属性。 |
text() | 选取文本。 |
目标URL: http://www.jokeji.cn/jokehtml/%E5%86%B7%E7%AC%91%E8%AF%9D/2020080419273330.htm
在前面学习了xpath的语法,那么在python爬虫代码中我们如何使用xpath呢? 对应的我们需要lxml
pip install lxml
导入lxml 的 etree 库 (导入没有提示不代表不能用)
from lxml import etree
利用etree.HTML,将字符串转化为Element对象,Element对象具有xpath的方法,返回结果的列表,能够接受bytes类型的数据和str类型的数据
html = etree.HTML(text)
ret_list = html.xpath("xpath字符串")
把转化后的element对象转化为字符串,返回bytes类型结果 etree.tostring(element)
假设我们现有如下的html字符换,尝试对他进行操作
目标URL: http://www.jokeji.cn/jokehtml/%E5%86%B7%E7%AC%91%E8%AF%9D/2020080419273330.htm
//span[@id='text110']/p
//div[@class='zw_page1']/a
import requests
from lxml import etree
"""jokehtml/冷笑话/2020080419273330.htm""" # 头页结点
class Joke:
def __init__(self):
self._count = 1
def get(self, url, page):
self._url = "http://www.jokeji.cn/" + url # 拼接组建新页的URL
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36",
"Referer": "http://www.jokeji.cn/list43_1.htm"
}
response = requests.get(self._url, headers)
self.analytical(response, page)
def analytical(self, response, page):
html = etree.HTML(response.content.decode("gbk"))
if self._count < page:
self._count += 1
node = html.xpath("//div[@class='zw_page1']/a/@href")[0][5:] # 提取下一页的url节点
self.get(node, page)
jokes = html.xpath("//span[@id='text110']/p/text()") # 解析笑话节点
for joke in jokes:
print(joke)
print("===" * 15)
if __name__ == '__main__':
joke = Joke()
joke.get("jokehtml/冷笑话/2020080419273330.htm", 10)
百度音乐【千千音乐】 https://music.taihe.com/
要求输入歌手名字即可返回其的歌曲,及链接(4 星)
参考答案 提取码:2pfv
"""
本次练习比较复杂,没有加入翻页功能,翻页的URL在JS里边,需要对网站JS代码进行进一步的剖析
涉及知识点:
1.reuqests的使用,headers、params参数等
2.用户ip代理
3.多种反反爬手段
4.Json数据提取 json结构分析
5.Xpath数据提取 xpath数据定位
6.jsonpath模块的使用
7.lxml模块的使用
8.retrying模块的使用
9.文件的读写
10.系统操作
"""