IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 分析Ajax抓取今日头条街拍图片(关于使用page_num且获取不到json对象的解决办法) -> 正文阅读

[JavaScript知识库]分析Ajax抓取今日头条街拍图片(关于使用page_num且获取不到json对象的解决办法)


本文,我们以今日头条为例来尝试通过分析Ajax请求来抓取网页数据的方法。这次要抓取的目标是今日头条的街拍图片,抓取并保存。本节代码是参照python3网络爬虫实战的6.4节,但由于现在网页有的东西已经做了更新,所以本文代码也做了相应的修改,使得其可以正常抓取数据。

1.准备工作

首先,请确保安装好requests库。

2.抓取分析

在抓取之前,首先要分析抓取的逻辑。打开今日头条的首页https://www.toutiao.com/,如图
在这里插入图片描述
在搜索框输入街拍,结果如图所示
在这里插入图片描述

点击图片,切换到图片分类中
在这里插入图片描述
这时打开开发者工具,查看所有的网络请求。首先,打开第一个网络请求,这个请求的URL就是当前的连接https://so.toutiao.com/search?keyword=%E8%A1%97%E6%8B%8D&pd=atlas&source=search_subtab_switch&dvpf=pc&aid=4916&page_num=0,打开Preview选项卡查看Response Body。发现页面只有一部分,如图,可以分析后面的图片数据是由Ajax加载,然后用JavaScript渲染出来的。
在这里插入图片描述
接下来,我们可以切换到XHR过滤选项卡,查看有没有Ajax请求。
果然,这里出现了一个比较常规的Ajax请求,看看它的结果是否包含了页面中的相关数据。
点击rawData字段展开,可以发现里面有一个data字段,还有count字段为40,意思是这条请求包含40个图片,data字段里包含40条记录,分别是图片的url,以及其他信息。
在这里插入图片描述
这就确定了这些数据确实是由Ajax加载的。
我们的目的是要抓取其中的图片,这里一组图就对应前面data字段中的一条数据。如图所示
在这里插入图片描述
因此,我们只需要将data中每条数据的img_url字段提取并下载下来就好了。建立一个文件夹保存这些图片。
接下来,我们就可以直接用Python来模拟这个Ajax请求,然后提取相关信息。但是在这之前,我们还需要分析一下URL的规律。
切换回Headers选项卡,观察一下它的请求URL和Headers信息,如图
在这里插入图片描述
可以看到,这是一个GET请求,请求的参数有keyword、pd、source、dvpf、aid、page_num、search_json、rawJSON、search_id,我们需要找出这些参数的规律,因为这样才可以方便用程序构造请求。
接下里,滑动界面,多加载一些结果。在加载的同时可以发现,NetWork中又出现了许多Ajax请求,如图:
在这里插入图片描述
这里观察一下前后几个连接的请求变化,发现只有page_num参数在变化,每次的变化为1,所以可以发现规律,这个page_num就是偏移量,进而可以推断出count参数就是一次性获取的数据条数。因此我们可以用page_num参数来控制分页。这样就可以通过接口批量获取数据了,然后将数据解析,将图片下载即可。另外,我们发现keyword参数使用的并不是明文,而是经加密后的代码,我们可以借助python中的unquote包来解决。

3.实战演练

我们刚才已经分析了一下Ajax请求的逻辑,下面使用程序来实现。
首先,实现方法get_page()来加载单个Ajax请求的结果。其中唯一的变化就是参数page_num,所以把他当作参数传递,另外需要注意的是这里需要构造请求头,并且需要包含cooike,否则会获取不到Response,信息可以在Headers选项卡中找到:
在这里插入图片描述
而构造参数可以在payload选项卡中找到
在这里插入图片描述

import requests
from urllib.parse import urlencode,quote,unquote

headers = {
    'Host': 'so.toutiao.com',

    'Referer': 'https://so.toutiao.com/search?keyword=%E8%A1%97%E6%8B%8D&pd=atlas&dvpf=pc&aid=4916&page_num=0&search_json={%22from_search_id%22:%222022040316335201021218304330C35A48%22,%22origin_keyword%22:%22%E8%A1%97%E6%8B%8D%22,%22image_keyword%22:%22%E8%A1%97%E6%8B%8D%22}',

    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36',

    'X-Requested-With': 'XMLHttpRequest', # Ajax请求需要手动设置这里

    'Cookie': 'passport_csrf_token=92a1b4e0108fb8384f5b81554b5b5424; tt_webid=7053044990251386398; _S_DPR=1.25; _S_IPAD=0; MONITOR_WEB_ID=7053044990251386398; ttwid=1%7CoqMwjUw5WGRdjYizT8quhnfpAchk3v_E3YLa1riJgrY%7C1648972603%7Cbaea5aebf3461426baaede977fa55b0efec3033a9f0d6a3e26684ba80f607ee9; _S_WIN_WH=1536_722'

}

def get_page(page_num):
    params = {
        'keyword':unquote('%E8%A1%97%E6%8B%8D') ,
        'pd':'atlas',
        'dvpf':'pc',
        'aid': '4916' ,
        'page_num':page_num,
        'search_json':{"from_search_id":"2022040316335201021218304330C35A48","origin_keyword":"街拍","image_keyword":"街拍"},
        'rawJSON':'1',
        'search_id':'2022040317334901015013503043241DAC'
    }
    url = 'https://so.toutiao.com/search/?'+urlencode(params,headers)
    try:
        response = requests.get(url,headers=headers,params=params)
        if response.status_code == 200:
            return response.json()
    except requests.ConnectionError:
        return None

这里我们用urlencode()方法构造请求的GET参数,然后用requests请求这个链接,如果返回状态码是200,则调用response的json()方法将结果转为JSON格式,然后返回。
接下来,再实现一个解析方法:提取每条数据的img_url字段中的图片链接,将图片链接返回,此时可以构造一个生成器。实现代码如下:

def get_images(json):
    if json.get('rawData'):
        images = json.get('rawData').get('data')
        for image in images:
            link = image.get('img_url')
            yield {
                    'image':image.get('img_url'),
                    'title':"街拍",
                    'text':image.get('text')
                }

接下来,实现一个保存图片的方法save_image(),其中item就是前面get_images()方法返回的一个字典。在该方法中,首先根据item的title创建文件夹,然后请求这个图片链接,获取图片的二进制数据,以二进制形式写入文件。图片的名称可以使用其内容的MD5值,这样可以去除重复。代码如下:

import os
from hashlib import md5

def save_image(item):
    if not os.path.exists(item.get('title')):
        os.mkdir(item.get('title'))
    try:
        response = requests.get(item.get('image'))
        if response.status_code == 200:
            file_path = '{0}/{1}.{2}'.format(item.get('title'),md5(response.content).hexdigest(),'jpg')
            if not os.path.exists(file_path):
                with open(file_path,'wb') as f:
                    f.write(response.content)
            else:
                print("Already Downloaded",file_path)
    except requests.ConnectionError:
        print('Failed to Save image')

最后,只需要构造一个数组,遍历,提取图片链接,并将其下载即可:

from multiprocessing.pool import Pool

def main(page_num):
    json = get_page(page_num)
    for item in get_images(json):
        print(item)
        save_image(item)

GROUP_START = 1
GROUP_END = 20

if __name__ == '__main__':
    # pool = Pool()
    # groups = ([x*20 for x in range(GROUP_START,GROUP_END+1)])  #使用这种方式启动出现bug,原因还没有找到
    # pool.map(main,groups)
    # pool.close()
    # pool.join()
    for i in range(1,10):
        main(i)

由于博主使用线程池出现bug,还未找到原因,所以先使用for循环
运行结果如下:
在这里插入图片描述
最后,给出本文代码地址:https://github.com/jiangwenvae/Spider/blob/main/spider/TouTiaoAjax.py

参考文献

[1].Python3网络爬虫开发实战.崔庆才.——6.4
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-04 12:02:05  更:2022-04-04 12:02:38 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 2:23:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码