爬虫之Json模块的应用
一:json简介
JSON(JavaScript Object Notation):是一种轻量级的数据交换格式。JSON数据格式类似与python中的字典
{} 花括号表示对象
[] 中括号表示数组
“” 双引号内是属性或值
: 表示后者是前者的值(这个值可以是字符串,数字,也可以是另一个数组或对象)
JSON格式数据查询举例:
# 变量格式为一个对象,key为一个字值,value是一个数组
var persons = {
"person":[
{"name":"张三", "age":23, "gender":true},
{"name":"李四", "age":23, "gender":true},
{"name":"王五", "age":23, "gender":true}
]
}
# 获取王五的年龄
persons.person[2].age
# 变量格式为一个数组,数组中含有多个对象
var persons = [
{"name":"张三", "age":23, "gender":true},
{"name":"李四", "age":23, "gender":true},
{"name":"王五", "age":23, "gender":true}
]
# 获取王五的年龄
persons[2].age
JSON和Python字典数据类型对应
python数据类型 | JSON数据类型 |
---|---|
dict | object |
list, tuple | array |
str, unicode | string |
int, long, float | number |
True | true |
False | false |
None | null |
二:JSON模块在爬虫中的应用
案例一:json模块的方法
import json
# json格式数据其实就是一个字符串,只不过字符串中的个格式是{对象}/[数组]
# 定义json格式数据,字符串里面的内容是单引号包裹的
# 注:一定是单引号包双引号的格式
json_data = '{"name":"zhangsan", "age":20}'
# json模块方法
# json.loads(),将json格式的数据转为python类型
result = json.loads(json_data)
print(result) # 结果为:{"name":"zhangsan", "age":20}
print(type(result)) # <class "dict">
# json.dumps(),将python类型转换为json格式数据
# data = {"name":"zhangsan", "age":20}
# res = json.dumps(data)
# print(res) # {"name":"zhangsan", "age":20}
# print(type(res)) # <class "str">
# json.dump(),将python类型转换成json格式的数据,并保存至文件
# 文件的write只能写入字符串,故可用json.dump将其他类型转为字符串并保存
data = {"name":"zhangsan", "age":30}
with open("json_test.txt", "w", encoding="utf8") as f:
json.dump(data, f)
# json.load() 将json格式数据转换为python类型,并读取文件内容
with open("json_test.txt", "r", encoding="utf8") as f:
content = json.load(f)
print(content) # {"name":"zhangsan", "age":20}
print(type(content)) # <class "dict">
案例二:爬取高德地图北京天气状况
import requests
import json
headers = {
"User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:83.0) Gecko/20100101 Firefox/83.0"
}
response = requests.get(
url="https://www.amap.com/service/weather?adcode=110000",
headers = headers
)
# print(response.text) # 得到的数据类型为json数据类型
# 需先将json数据类型转换为python的字典类型,然后获取需要的信息
data_dic = json.loads(response.text)["data"]["data"][0]["forecast_data"][0]
# 获取最高气温
max_temp = data_dic["max_temp"]
# 获取最低气温
min_temp = data_dic["min_temp"]
# 获取天气
weather_name = data_dic["weather_name"]
print(max_temp, min_temp, weather_name)
案例三:获取全部城市的天气状况
第一步:寻找规律
# 先找出几个城市天气的地址,然后去寻找规律
# https://www.amap.com/service/weather?adcode=110000 北京
# https://www.amap.com/service/weather?adcode=120000 天津
# https://www.amap.com/service/weather?adcode=320100 南京
# 通过以上的url可以发现,不同城市的天气状况只有adcode不同
# 所以我们只要获取到所有城市的adcode即可得到全部城市的天气状况
第二步:寻找adcode
# 我们发现,f12后在各个请求中无法找到城市列表,但并不表示没有这个列表
# 这时,我们可以看到一个cityList?version=的请求,打开它的请求头
# 发现它的status是304
# 304(Not Modified):代表使用了缓存技术
# 如果客户端请求的状态码是304,代表发送了一个带有条件的额请求,并且此请求被允许,但是文档没有修改
# 请求头:If-None-Match: W/"192ab-iXUSEiwloSt5qDr2EMy0Wkzuv+M"
# 响应头:ETag: W/"192ab-iXUSEiwloSt5qDr2EMy0Wkzuv+M"
# 此时需要清理缓存,清理后即可看及那城市列表
第三部:爬取
# 需求:完成全部城市的天气情况获取,并保存到excel表格中
import requests
import json
# 定义请求头
headers = {
"User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:83.0) Gecko/20100101 Firefox/83.0"
}
response = requests.get(
url = "https://www.amap.com/service/cityList?version=",
headers = headers
)
# 得到一个包含城市列表的字典,并将它转换为python格式
city_dic = json.loads(response.text)["data"]["cityByLetter"]
# 定义一个天气url
weather_url = "https://www.amap.com/service/weather?adcode={}"
for city_list in city_dic.values():
for city in city_list:
# 获取城市的名字
city_name = city["name"]
# 获取城市的adcode
adcode = city["adcode"]
# 现在已经获取到了adcode,根据adcode可爬取全部城市的天气状况
weather_response = requests.get(
url = weather_url.format(adcode),
headers = headers
)
temp_list = json.loads(weather_response.text)["data"]["data"][0]["forecast_data"][0]
# 获取最高温度和最低温度
max_temp = temp_list["max_temp"]
min_temp = temp_list["min_temp"]
weather_name = temp_list["weather_name"]
print(city_name, weather_name, max_temp, min_temp)
第四步:将爬取到的数据保存到excel中
# 需求:完成全部城市的天气情况获取,并保存到excel表格中
import requests
import json
# 保存excel需要安装openpyxl模块
from openpyxl import Workbook
# 实例化Workbook对象
wb = Workbook()
# 激活工作表
ws = wb.active
# 添加表头
ws.append(["城市名","天气","最低气温","最高气温"])
# 定义请求头
headers = {
"User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:83.0) Gecko/20100101 Firefox/83.0"
}
response = requests.get(
url = "https://www.amap.com/service/cityList?version=",
headers = headers
)
# 得到一个包含城市列表的字典,并将它转换为python格式
city_dic = json.loads(response.text)["data"]["cityByLetter"]
# 定义一个天气url
weather_url = "https://www.amap.com/service/weather?adcode={}"
for city_list in city_dic.values():
for city in city_list:
# 向excel中添加数据时是以列表的形式一一对应进行添加的
lst = list()
# 获取城市的名字
city_name = city["name"]
# 获取城市的adcode
adcode = city["adcode"]
# 现在已经获取到了adcode,根据adcode可爬取全部城市的天气状况
weather_response = requests.get(
url = weather_url.format(adcode),
headers = headers
)
temp_list = json.loads(weather_response.text)["data"]["data"][0]["forecast_data"][0]
# 获取最高温度和最低温度
max_temp = temp_list["max_temp"]
min_temp = temp_list["min_temp"]
weather_name = temp_list["weather_name"]
# 保存到列表中
lst.append(city_name)
lst.append(weather_name)
lst.append(min_temp)
lst.append(max_temp)
ws.append(lst)
# 保存数据
wb.save("all_weather.xlsx")