爬虫之爬取知乎下某个问题下的全部图片(处理AJAX请求,解析json数据)

本文介绍了如何使用Python爬虫处理AJAX请求,解析JSON数据,以获取知乎问题下所有页面的图片。通过观察请求头和Query String Parameters中的offset值变化,了解到每页20条回答的规律,从而实现动态加载内容的抓取。文中提供了具体的代码实现。
摘要由CSDN通过智能技术生成

(直接需要代码的看最后面,前面只是分析)  

当你查看知乎某个问题的答案时,通过普通的方法爬取页面,你发现只能爬取一页的内容,当你点击下一页时,浏览器地址并没有发生变化,这种技术叫做AJAX,每次载入的只是部分数据,当知道这个后,就可以构造特殊的头部来请求获得数据。

知乎问题下的解析:

可以看到请求页面的方式GET,请求的地址为Request URL,请求头的构成为Request Header的内容,有点长是不是。


Request Header



还有一个就是Query String Parameters


 

这是什么呢,这就是我们Request URL的请求的数据部分了,他是怎么区分页面的呢,我们看第二页的请求数据



两者不同的是 offset这个值,而知乎一个页面的回答数量刚好是20,也就是差值。


到这里我们就可以知道怎么样获取我们请求的数据了:

用GET方法向指定URL发送我们的请求数据


下面是代码实现:

import urllib.request
import json
import urllib.parse
import re
import random
n=0
for i in range(0,10):                                                                           #爬取十页的回答的图片
    url='https://www.zhihu.com/api/v4/questions/27761934/answers?'                      #请求URL地址
    data={}
    head={}
    #head为请求头部封装
    head['User-Agent']='Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36'
    head['accept']='application/json, text/plain, */*'
    # head['Accept-Encoding']='utf-8, deflate, sdch, br'
    head['Accept-Language']='zh-CN,zh;q=0.8'
    head['Referer']='https://www.zhihu.com/question/27761934'
    head['authorization']='oauth c3cef7c66a1843f8b3a9e6a1e3160e20'
    head['Connection']='keep-alive'
    head['host']='www.zhihu.com'
    head['Cookie']='q_c1=cb235bc32c3c4ff6a13d539ab32932ed|1491640993000|1491640993000;' \
                   ' r_cap_id="OTk4MDc1ZTYzZTYxNDhkMGFkZmMzZmMyY2MzYTQ0MWM=|1492689948|ea65e09abdd21db7eecd997d1e7689d7213005c8"; ' \
                   'cap_id="ZWY2NDA1MTc3ZjAzNDc2MWFmNTQ4YjFkY2NhNzdmZjM=|1492689948|16df8cfc942dcae5adc9ffa5395afbdcc87bf39a";' \
                   ' l_cap_id="ZGNkOGVmZTgzNDk0NGJjOTljMzU0Mjc0MGY2YmU1ODE=|1492689948|2768d12cd0236bb96722f7216b307ba799d4bf19"; ' \
                   'aliyungf_tc=AQAAABxPakPO4goAgVG3PSefHqc6PP2k; acw_tc=AQAAAEUxcRqsHQwAgVG3PZaK3p0hk5Lq'
    #data为数据部分
    data['sort_by']='default'
    data['include']='data[*].is_normal,is_sticky,collapsed_by,suggest_edit,comment_count,' \
                    'can_comment,content,editable_content,voteup_count,reshipment_settings,' \
                    'comment_permission,mark_infos,created_time,updated_time,' \
                    'relationship.is_authorized,is_author,voting,is_thanked,is_nothelp,' \
                    'upvoted_followees;data[*].author.badge[?(type=best_answerer)].topics'
    data['limit']=20
    data['offset']=3+20*i

    data=urllib.parse.urlencode(data).encode('utf-8')
    req=urllib.request.Request(url,data,head,method='GET')
    #需指定方法,默认是为POST的
    req = urllib.request.urlopen(req)
    re_data = req.read().decode('gbk')
    print(re_data)
    pe='https:.{0,80}jpg'                                                   #构造的正则,有点丑陋。。。
    url1=re.compile(pe)
    num=0

    q=random.randint(1,20)
    for x in url1.findall(re_data):
        if 'https'  in x:
            print(x)
            try:
                if(num%4==0):
                    urllib.request.urlretrieve(x, 'F:\\ccc3\\test\\mmmmmm'+str(q)+'%s.jpg' % num)
                    print('下载第'+str(n) + '张图片')
                    n+=1
            except:print('error')
            num +=1









其中head的cookie,host,connection等都是可以省略的。
已知缺陷:json里同一个链接出现四次,我用num处理的有点难看
有最大爬取数,不超过一千,可以用ip池解决
正则丑陋。
爬取别的问题需要修改的是URL里的数字及head['Referer']里的数字,数字为问题的代码,代码为:

里面的数字,如果代码不能运行请修改cookie和authorization为自己的.
如还不能运行,评论或者私信我








   
   



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值