【4】实战:爬取动态网页的两种思路爬取新浪趣图(1)

第三篇末尾提到了,在这里我们就以爬取新浪趣图上的gif图来演示介绍过的两种爬取动态网页的方法:

1.分析网页,找到AJAX传递数据的地址,并分析数据,通常是Json格式储存的数据;(详见【2】分析JSON获取数据)

2.运用selenium模拟浏览器环境,最新python对PhantomJS不再支持,故搭档chrome。(详见:【3】selenium+chrome)

其中,我记得在第二篇中,包含了基于爬取股票信息从而详细得介绍如何分析Json数据以及如何模仿人的行为的实战

话不多说,今天我们的目标就是用以上两种方法爬取新浪每日趣图中的GIF图片到本地。

最后也将基于这次实战,简单分析一下这两种方法的利弊。不过话提前说,通常能用第一种不要用第二种!

详细源码请见:源码-github。本文使用第一种方法。

一、分析网页获取数据:

1.分析传递异步加载信息的网页

老规矩,我们进网页之后,检查图片元素,看其标签位置,之后再查看网页源代码寻找相应标签。

之后会发现源代码中的相应位置并没有我们想要的数据,这说明我们想要的数据就是动态网页异步加载出来的东西。

再下一步,就要合理运用开发者工具,在Network中的XHR或者JS中分析哪个文件包含异步加载的信息。

我们不难从JS中分析到中储存我们想要的数据。

2.解析格式化Json信息

这个例子中,我们发现我们可以直接进入该网页,也就是说,网站并没有设置障碍(相较于第二篇中股票信息会出现403错误码),那么也就是说,我们不需要设置特定的‘人’的信息。

那么我们将传递数据的网址中的信息放入json在线解析和格式化中验证其是否是标准的json数据。

不出所料,并不是

这次的修改也相对较为简单,只需要将最前面的‘{’之前的所有信息删除,最后面的‘}’后面的‘)’也删除即可看到解析出的格式化json信息。

3.寻找目标信息在json中的位置

我们要寻找我们所需要的图片地址,根据之前所介绍的jsonpath定位方式,我们不难发现其表示为:‘$..img_url’

【4】实战:爬取动态网页的两种思路爬取新浪趣图(1)_第1张图片

此外,我们通过点击第二页通过对比:

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 #第二页

不难发现,页数的改变只需改变'page='后面的数字

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秒的时间即下载完成并执行完毕。

下篇我们继续讲解第二种方法并比较其时间。

你可能感兴趣的