第三篇末尾提到了,在这里我们就以爬取新浪趣图上的gif图来演示介绍过的两种爬取动态网页的方法:
1.分析网页,找到AJAX传递数据的地址,并分析数据,通常是Json格式储存的数据;(详见【2】分析JSON获取数据)
2.运用selenium模拟浏览器环境,最新python对PhantomJS不再支持,故搭档chrome。(详见:【3】selenium+chrome)
其中,我记得在第二篇中,包含了基于爬取股票信息从而详细得介绍如何分析Json数据以及如何模仿人的行为的实战。
话不多说,今天我们的目标就是用以上两种方法爬取新浪每日趣图中的GIF图片到本地。
最后也将基于这次实战,简单分析一下这两种方法的利弊。不过话提前说,通常能用第一种不要用第二种!
详细源码请见:源码-github。本文使用第一种方法。
一、分析网页获取数据:
1.分析传递异步加载信息的网页
老规矩,我们进网页之后,检查图片元素,看其标签位置,之后再查看网页源代码寻找相应标签。
之后会发现源代码中的相应位置并没有我们想要的数据,这说明我们想要的数据就是动态网页异步加载出来的东西。
再下一步,就要合理运用开发者工具,在Network中的XHR或者JS中分析哪个文件包含异步加载的信息。
2.解析格式化Json信息
这个例子中,我们发现我们可以直接进入该网页,也就是说,网站并没有设置障碍(相较于第二篇中股票信息会出现403错误码),那么也就是说,我们不需要设置特定的‘人’的信息。
那么我们将传递数据的网址中的信息放入json在线解析和格式化中验证其是否是标准的json数据。
这次的修改也相对较为简单,只需要将最前面的‘{’之前的所有信息删除,最后面的‘}’后面的‘)’也删除即可看到解析出的格式化json信息。
3.寻找目标信息在json中的位置
我们要寻找我们所需要的图片地址,根据之前所介绍的jsonpath定位方式,我们不难发现其表示为:‘$..img_url’
此外,我们通过点击第二页通过对比:
http://platform.sina.com.cn/slide/album?app_key=2733610594&format=json&ch_id=77&num=10&page=1&jsoncallback=getDataJson #第一页
http://platform.sina.com.cn/slide/album?app_key=2733610594&format=json&ch_id=77&num=10&page=2&jsoncallback=getDataJson #第二页
4.开始爬取数据
import requests
import json
from jsonpath import jsonpath
import urllib
import time #导入库
def url_get(page_num):#获取所需的数据页
url='http://platform.sina.com.cn/slide/album?app_key=2733610594&format=json&ch_id=77&num=10&page='+str(page_num)+'&jsoncallback=getDataJson'
return url
def fetch_img(pages):#抓取并下载图片
if(pages>1000):#要求下载页数过多则放弃
exit()
page_num=1
while(page_num<=pages):#直到收集到要求的页数
response=requests.get(url_get(page_num))
data_json=response.text[12:-1]#json格式化
data_unicode=json.loads(data_json)
title=jsonpath(data_unicode,"$..name")
img=jsonpath(data_unicode,"$..img_url")#筛选出标题和图片
for x,y in zip(img,title):#输出到屏幕标题和图片地址的对应关系
data={'title':y,
'img':x}
print(data)
num=1
for x in img:#下载图片到本地
urllib.request.urlretrieve(x,'%d:%s%d.gif'%(page_num,time.ctime()[:7]+time.ctime()[-4:],num))
num+=1
page_num+=1
#time.sleep(2)#可有可无
以上,即第一种方法
调用fetch_img(2),会发现不出2-3秒的时间即下载完成并执行完毕。
下篇我们继续讲解第二种方法并比较其时间。