【python爬虫】动态加载页面的解决办法(以ins为例)

现在很多的web页面使用ajax技术动态加载页面。但对于爬虫来说,目标数据很可能不在页面HTML源码中(右键查看网页源代码,通过F12查找),针对静态页面的爬虫不再满足现在的需求。

很多教程都推荐用Selenium和PhantomJS配合使用,实现网页的渲染,得到网页的全部信息。但是对于爬虫程序,模拟浏览器内存开销实在是非常大,而且效率低

好消息是,大多是是浏览器会在请求和解析HTML之后,根据js的“指示”再发送一次请求,得到页面展示的内容,然后通过js渲染之后展示到界面。这样的请求往往得到的内容是json格式的,所以我们非但不会加重爬虫的任务,反而可能会省去解析HTML的功夫。

本文以爬取instagram上的某位明星上传的全部图片为例讲解动态加载页面的解决办法。文末附上全部代码大笑

工具:Chrome

包:json,requests,urllib

分析ins页面


某用户的主页

打开某用户ins主页(https://www.instagram.com/urnotchrislee/?hl=zh-cn)可以看到,首页只加载了12张图片,要点击“更多”才会加载更多的图片。我们先获取这12张图片的URL。


获取前12张图片的URL

首先检查源码中是否存在图片的URL。在script标签中发现前12张图片的URL。


网页源码

有了这个发现,我们就可以提取首页的12张图片URL!!

代码如下:



通过使用lxml库实现解析,不了解lxml的童鞋可以去崔大神的博客 学习学习。

获取更多图片的URL

在点击“更多”按键时,发现XHR选项卡中加载了一些新文件。


加载前


加载后

每一次下拉页面都会加载出12张图片,“?query_idbalabala”文件也会增加一个!


点击文件查看详细信息。发现该文件返回json数据,并且数据中包含我们要的图片URL!!


返回的json数据

所以说只要获取到这些json数据,我们就能提取出更多的图片URL。



请求信息

请求信息

请求信息

仔细看上图的Request URL,让我们分析下它的请求参数(包括query_id,id,first,after)可以看到后续加载的query_id都为“17888483320059182”,“id”为你所访问的用户的用户id,为“1161353543”,“first”为一次加载的图片数,始终为12。“after”比较复杂。但是按常理来说,这个参数应该在前面的文件中能够找到。

找“after”

利用ctrl+F在页面源码中找到了after参数对应的值。同样是在script标签中,不过对应的键名是“end_cursor”


凑齐了四个请求参数,这下我们可以构造Request URL,通过解析返回的json数据,获取更多的图片URL了得意

代码如下:



src_list中存储了该用户590张图片的URL,现在该进入到下载环节啦~

下载图片

博主懒得换代理,直接用来最简单粗暴的方式下载了图片。


结果展示~



全部代码

# -*- coding: utf-8 -*-
import json
import requests
from lxml import etree
from urllib import parse

BASE_URL = "https://www.instagram.com/urnotchrislee/"
headers = {
    "Origin": "https://www.instagram.com/",
    "Referer": "https://www.instagram.com/urnotchrislee/",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
                  "Chrome/58.0.3029.110 Safari/537.36",
    "Host": "www.instagram.com"}

def load_rest(table,has_next_page):
    rest = []
    while has_next_page:
        text = json.dumps(table)
        URL = 'https://www.instagram.com/graphql/query/?query_id=17888483320059182&variables='+parse.quote(text)
        res = requests.get(URL,headers = headers)
        dic = json.loads(res.content.decode(),encoding='utf-8')
        
        data = dic['data']['user']['edge_owner_to_timeline_media']
        nodes = data['edges']
        end_cursor = data['page_info']['end_cursor']
        has_next_page = data['page_info']['has_next_page']
        
        for node in nodes:
            rest.append(node['node']['display_url'])
            #print(node['node']['display_url'])
        table['after'] = end_cursor
        print('加载..')  
    print('加载完成') 
    return rest 

if __name__=='__main__':

    res = requests.get(BASE_URL,headers = headers)
    html = etree.HTML(res.content.decode())
#    h = html.xpath('''//script[@type="text/javascript"]/text()''')[1].replace('window._sharedData =','').strip()
    h = html.xpath('''//script[@type="text/javascript"]''')[1].text.replace('window._sharedData = ','').strip()[:-1]
    dic = json.loads(h,encoding='utf-8')

    data = dic['entry_data']['ProfilePage'][0]['user']['media']
    nodes = data['nodes']
    end_cursor = data['page_info']['end_cursor']
    has_next_page = data['page_info']['has_next_page']
    lee_id = nodes[0]["owner"]["id"]  #'1161353543'
    
    src_list = []
    for node in nodes:
        src_list.append(node['display_src'])
        print(node['display_src'])
    print('加载')   
    
    table = {
             'id':lee_id,
             'first':12,
             'after':end_cursor}
    rest = load_rest(table,has_next_page)
    src_list = src_list + rest
    print(len(src_list))
    
#    with open('abc', 'w') as f:
#    for s in src_list:
#        f.write(s)
#        f.write('\n')     

    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
                      "Chrome/58.0.3029.110 Safari/537.36",}
    for i in range(len(src_list)):
        url = src_list[i].strip()
        res = requests.get(url,headers = headers)
        with open('第'+str(i+1)+'张.jpg','wb') as ff:
            ff.write(res.content)



参考网页:

Web crawler with Python - 04.另一种抓取方式

Python之Instagram图片爬虫(一)

Python之Instagram图片爬虫(二) 

新手小白,逻辑混乱,欢迎大佬指正错误,求轻喷



  • 9
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值