爬虫python实例,python爬虫实战案例
学习笔记
文章目录Ajax动态加载网站数据抓取动态加载的类型那么如何抓取数据呢?如何获取JSON文件的地址?观察JSON文件URL地址的查询参数。如何将JSON格式数据转换成python字典获取科研数据
前几天小伙伴在写报告的时候,讨论了一个生态网站的抓取统计问题。我看了看,想了想。很多数据网站的数据都是动态加载的,写个案例就好,方便数据收集整理。
在爬取数据之前,我先讲一些关于动态加载网站的知识点,让你理解代码。
动态加载的类型部分页面刷新的动态加载
首先,我们来看一个动态加载的网站(这个网站也是我们后面要抓取的网站):
当我们翻页时,URL地址不会改变。网站只刷新部分页面,只有表格中的数据发生变化,而页面的其余部分没有变化:
滚动自动触发页面加载。
我们来看一个大家都很熟悉的动态加载网站,某东。当我们在一个东页搜索【华章数学】时,会出现以下页面:
我们检查这些元素,以查看当前页面中最后一项的HTML结构:
通过观察,我们发现每个商品都被包裹在一个li标签中,那么当前页面的最后一个商品应该被包裹在最后一个li标签中。现在让我们滑动鼠标滚轮,并在滑动页面时观察HTML页面结构:
哦亲爱的!我们发现滑到底部,页面自动加载了很多李标签包装的新品,页面的URL地址不变。
那么,如何获取数据呢?
我们可以看到在动态加载的页面下,URL很弱,无法使用静态匹配的方法抓取动态加载页面中的数据,那么如何抓取信息呢?
需要注意的是!只要是动态加载的网站,当我们与网站进行交互时,网站都会以JSON格式返回给我们信息,其中包含了我们要抓取的数据。至此,只要找到这些JSON文件的地址,就已经大获成功了。
如何获取JSON文件的地址?
我们使用的数据来自安徽省生态与环境厅(http://sthjt.ah.gov.cn/site/tpl/5391?CityCode=340100)为例,我们发现在这个网页中翻页时,只有部分页面信息被刷新,页面的URL地址保持不变,所以网站应该是动态加载数据的。
打开某#省生态环境厅网页后,右键打开审核元素——点击网络——点击全部——翻页,获取网站与我们交互的数据包——点击预览,确定数据包中是否有我们想要的数据——点击表头,查看数据包的表头信息:
让我们注意一下Headers中基本请求信息(General)中的请求URL。这个URL地址就是我们需要的JSON文件的URL地址。让我们打开这个地址来验证:
非常好!那是你。但是…这些JSON数据的格式看起来很混乱。这么多\转义字符是怎么回事?虽然这个问题不影响我们以后的数据抓取,但是我会先标记这个问题,以后再解决。
让我们回到请求头的头,看看查询参数:
这些查询参数是JSON文件的URL地址的查询参数。如果你不相信我,我们来对比一下这些查询参数和JSON文件的URL地址:
#JSON文件的URL地址
http://sthjt.ah.gov.cn/site/label/8888?isa jax=1 dataType=JSON _=0.6245771911926585 is JSON=true city code=340100 type=1 num=2 is page=true page index=3 pageSize=10 label name=air quality
#查询参数
伊萨亚斯:1
数据类型:json
_:0.6245771911926585
isJson:对
城市代码:340100
类型:1
数量:2
isPage:真的
页面索引:3
页面大小:10
标签:空气质量,嗯!没错!
那么这些查询参数有什么用呢?就像我们之前在抓取静态网页的数据时需要观察多个URL地址的查询参数的规则一样。如果我们要抓取动态页面中的数据,数据可能不仅仅在一两个JSON文件中,还可能在大量的JSON文件中。这时候我们需要通过观察查询参数的规则,批量获取我们需要的JSON文件的URL地址,从而获取JSON文件中的数据。
观察JSON文件URL地址的查询参数
我们通过多次翻页来观察查询参数的规律。
第1页:
伊萨亚斯:1
数据类型:json
_:0.9632859283976705
isJson:对
城市代码:340100
类型:1
数量:2
isPage:真的
页面索引:1
页面大小:10
名称:空气质量第2页:
伊萨亚斯:1
数据类型:json
_:0.699042424499402
isJson:对
城市代码:340100
类型:1
数量:2
isPage:真的
页面索引:2
页面大小:10
名称:空气质量第3页:
伊萨亚斯:1
数据类型:json
_:0.6245771911926585
isJson:对
城市代码:340100
类型:1
数量:2
isPage:真的
页面索引:3
页面大小:10
名称:空气质量我们发现除了_和pageIndex在翻页时发生了变化外,其他查询参数保持不变。
我对this _ query参数的规则有点困惑。让我们看看是否可以通过从URL地址中删除这个查询参数来访问JSON文件。
移除_ query参数后第3页JSON文件的URL地址:
http://sthjt.ah.gov.cn/site/label/8888?is Ajax=1 data type=JSON is JSON=true city code=340100 type=1 num=2 ispage=true page index=3 pagesize=10 label name=air quality访问结果:
当然可以!删除_ query参数并不妨碍我们获取JSON文件;同时我们对比网页第3页的数据,和一毛钱一样。
现在我们看pageIndex的查询参数,可以看到第一页的pageIndex的参数值是1,第二页是2,第三页是3,所以我们推断第二页的pageIndex的查询参数值是。现在我将pageIndex的参数值改为4,并访问这个URL地址:
对比网页中第4页的数据,完全一样。
JSON格式的数据被转换成python字典
现在我们已经整理好了JSON文件的URL地址,就可以抓取网页,获取网页内容了。但是!请注意,我们如何获取JSON文件中的数据?我们看到JSON的数据格式,有点像python中的字典和列表。要爬取的数据由数据键对应的值(一个列表)包装;每个记录都在一个列表中,包装在一个字典中:
{数据:[
{
aqi: 54 ,
区域:合肥市:
城市代码:340100,
一氧化碳: 0.363 ,
级别,级别: II ,
度量值: ,
第二名:“30分钟”,
o3: 115 ,
pm10: 57 ,
pm25: 16 ,
主要污染物:“颗粒物质(PM10)”,
质量:“好”,
二氧化硫: 7 ,
时间点: 2020-04-15 18:00:00 ,
不健康:“”
},
{
aqi: 49 ,
区域:合肥市:
城市代码:340100,
一氧化碳: 0.334 ,
级别,级别:我,
度量值: ,
第二名:“22”,
o3: 123 ,
pm10: 49 ,
pm25: 15 ,
primary pollutant:“—”,
质量:“优秀”,
二氧化硫: 7 ,
时间点: 2020-04-15 17:00:00 ,
不健康:“”
}],
页数:5,
pageIndex: 4,
页面大小:10,
起始号码:40,
总数:47
}但仔细观察后发现,这些数据格式与字典略有不同,不能直接用字典索引来获取数据。所以我们想把JSON格式的数据转换成python字典类型,方便获取数据。
但是怎么转换呢?
请求模块是我们的好帮手。使用requests.get()。json()方法可以直接返回python的数据类型。
语法:
Html _ str=requests.get (URL,headers=headers)。JSON()应该返回一个字典,但是!不知道为什么,它返回给我一个包含字典的字符串?我不要字符串,我要字典!现在我在网上找到了两种将字符串转换成字典类型的方法。让我们来演示一下:
In [43]: str_01={a:1}
在[44]中:键入(json.loads(str_01))
Out[44]:字典
在[45]中:键入(eval(str_01))
Out[45]:字典
如何获取科研数据?现在我们回到如何获取科研数据的问题上来。这里我就以我和朋友要爬的网站为例,也就是刚才一直在讲解的安徽省生态环境厅网站:
在这种情况下,我得到网页中的aqi(质量指数)、cityCode(城市代码)和pm25(PM2.5)的值。
PS:因为我懒得打那么多代码,你可以举一反三,得到其他变量值。
好,开始输入代码:
# -*-编码:utf-8 -*-
导入请求
导入时间
导入csv
导入json
类别DeeSpider:
def __init__(self):
self . URL= http://sth JT . ah . gov . cn/site/label/8888? isa jax=1 dataType=JSON is JSON=true city code=340100 type=1 num=2 is page=true page index={ } pageSize=10 label name=air quality
self . headers={ Accept : application/JSON,text/javascript,*/*;q=0.01 ,
接受-语言: zh-CN,zh;q=0.9 ,
连接:保持活动,
主持人: sthjt.ah.gov.cn ,
用户代理: Mozilla/5.0(Windows NT 6.3;WOW64) AppleWebKit/537.36 (KHTML,像壁虎一样)Chrome/63 . 0 . 3239 . 84 Safari/537.36 ,
x-Requested-With : XMLHttpRequest }
def get_data(self,url):
html=requests.get(url,headers=self.headers)。json()
#你得到的是一串。
打印(类型(html))
html _ dict=JSON . loads(html)[ data ]
#html_dict=html[data]
#用于循环每个记录的数据
data_list=[]
对于html_dict中的数据:
aqi=数据[aqi]
cityCode=data[cityCode]
pm25=数据[pm25]
#打印(城市代码)
data_list.append([aqi,cityCode,pm25])
self.write_data(数据列表)
def write_data(self,data_list):
带开(。/test/my_DeeData.csv , a ,newline= )作为f:
writer=csv.writer(f)
#writer.writerow([aqi , cityCode , pm25])
writer.writerows(data_list)
def main(自身):
对于范围(1,5)中的项目:
url=self.url.format(item)
self.get_data(url)
if __name__==__main__ :
start=time.time()
spider=DeeSpider()
spider.main()
end=time.time()
Print(执行时间:%.2f%(结束-开始))控制台输出:
类别“str”
类别“str”
类别“str”
类别“str”
执行时间:1.15部分数据爬下(共37次):
85,340100,63
93,340100,69
94,340100,70
92,340100,68
88,340100,65
85,340100,60
85,340100,49
82,340100,43
84,340100,44
87,340100,41
87,340100,35
3,340,100,31.很好!所有的数据都爬了下来。
但是要注意!虽然这个数据网站的页面上注明有47条数据,总共有5页,但实际上只有37条数据,我无法点击第五页:
将JSON的URL地址中的查询参数pageIndex设置为5,得到的响应是系统忙:啊
本案例讲完了,欢迎补充、指正和指导。
备注:虽然看起来我们花了这么多心思,数据不多,但重要的是要明白如何举一反三。
转载请联系作者获得转载授权,否则将追究法律责任。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。