简单爬虫Ajax数据爬取——今日头条图片爬取

2023-10-26

一、Ajax简介

什么是Ajax?

Ajax 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式网页应用的网页开发技术。

通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

传统的网页(不使用 Ajax)如果需要更新内容,必须重载整个网页页面。

我们在浏览很多网页,比如微博,我们点击进去某条微博,底下可以加载出网友的评论,但是我们可以看到网址是没有改变的,这就是使用了ajax技术。这次以爬取今日头条的图片为例来进行Ajax数据爬取的实战演示。本文也是学习自崔庆才博主的书籍。

二、逻辑分析

首先打开今日头条的网站:https://www.toutiao.com/,在搜索框内可以输入任意的内容,比如我爬取的是关于风景的图片。这里我使用的是谷歌浏览器,右键检查,选择NetWork,查看所有的网络请求。可以看到第一条网络请求就是当前的链接。点击这条请求,查看Response。如果我们这个网页是由这个请求的结果渲染出来的,那么这个请求的源代码中肯定会包含网页结果中的文字。这边可以使用搜索验证,比如搜索一下标题结果中的“破万”两个字,可以发现在这个请求中没有匹配的的结果。说明这些内容是由Ajax所加载的。

下面就可以分析Ajax请求了,Ajax的数据类型为xhr,这边可以在上面选择XHR,这样显示出来的就都是ajax请求,将网页从上拉到最下,可以看见请求逐渐变多。点击第一个请求,可以在右边看到显示出了不同的信息。

复制一下右边的Request URL,可以看到返回了json数据,所以我们的第一步就是分析请求url,获取返回的json数据。

三、加载单个Ajax请求

点击每个Ajax请求,可以看到他们的Request URL参数基本相同,唯一有变化的是offset,变化规律为每次+20,所以我们在实现方法是,传入offset作为参数。然后请求的方式为GET。

以第一个请求的url为例子:

https://www.toutiao.com/api/search/content/?aid=24&app_name=web_search&offset=0&format=json&keyword=%E9%A3%8E%E6%99%AF&autoload=true&count=20&en_qc=1&cur_tab=1&from=search_tab&pd=synthesis&timestamp=1557652705403

可以看到所有的参数,由次可以构造URL,然后请求这个链接,如果返回的状态码为200,那么就使用respnse.json()方法来将结果转化为json模式并返回。

#  唯一的变化就是offset
def get_page(offset):
    params = {
        'aid': '24',
        'offset': offset,
        'format': 'json',
        'autoload': 'true',
        'count': '20',
        'cur_tab': '1',
        'from': 'search_tab',
        'pd': 'synthesis'
    }
    base_url = 'https://www.toutiao.com/api/search/content/?keyword=%E9%A3%8E%E6%99%AF'  #这一部分都是相同的参数
    url = base_url + urlencode(params) # 构造请求的GET参数
    print(url) # 可以打印出url看自己构建的是否有效
    try:
        resp = requests.get(url)
        if 200 == resp.status_code:
            print(resp.json()) # 看下返回结果是否正确
            return resp.json()
    except requests.ConnectionError:
        return None

四、解析结果

我们在获取json结果后,就要从中解析提取出我们所要爬取的数据。点击data可以看见很多条数据,每条数据里都有一个image_list字段,包含了我们所要爬取的图片url,所以我们要在刚才返回的结果内将图片url提取出来,通过构造一个生成器,将图片链接和标题返回。

# 提取图片链接和图片标题
def get_images(json): # 将刚才的json传入
    if json.get('data'): # 找到data
        data = json.get('data')
        for item in data: # 找到data中标题和图片链接列表
            title = item.get('title')
            images = item.get('image_list')
            for image in images: # 构造生成器
                yield {
                    'image':  image.get('url'),
                    'title': title
                }

五、保存图片

将所有图片的url返回后,我们就需要一个方法来下载图片并保存。首先我们要根据返回的title值创建文件夹,然后请求这个图片链接,获取数据,以二进制形式写入文件。图片名称可以根据其内容的MD5值来命名。

# 保存图片方法
# 根据title创建文件夹,然后根据图片链接获取图片二进制文件,写入文件,图片名称为其内容的MD5值
def save_image(item):
    img_path = 'img' + os.path.sep + item.get('title') # os.path.sep这是路径分割符
    print(img_path)
    if not os.path.exists(img_path): # 如果不存在文件夹就创一个
        os.makedirs(img_path)
    try:
        resp = requests.get(item.get('image'))
        if codes.ok == resp.status_code:
            # 使用format方法格式化,生成文件路径
            file_path = img_path + os.path.sep + '{file_name}.{file_suffix}'.format(
                file_name=md5(resp.content).hexdigest(), # 将文件保存时,通过哈希函数对每个文件进行文件名的自动生成
                file_suffix='jpg')
            if not os.path.exists(file_path):
                with open(file_path, 'wb') as f: # 还未下载则写入文件内容
                    f.write(resp.content) 
                print('Downloaded image path is %s' % file_path)
            else:
                print('Already Downloaded', file_path)
    except requests.ConnectionError:
        print('Failed to Save Image,item %s' % item)

六、传入offset参数,多进程下载

def main(offset):
    json = get_page(offset)  # 获得json的返回结果
    for item in get_images(json):  # 解析json获得包括标题以及图片链接的词典item
        print(item)  # 打印处词典信息
        save_image(item)  # 保存图片


GROUP_START = 0 #offset最多到120
GROUP_END = 6

if __name__ == '__main__':
    pool = Pool()  # python多进程,创建进程池
    groups = ([x * 20 for x in range(GROUP_START, GROUP_END + 1)])  # 传入1到20的参数
    pool.map(main, groups)  # main表示要执行的方法, 后面表示被操作的数据列表
    pool.close()  # 关闭进程池,不再接受新的进程
    pool.join()  # 主进程阻塞等待子进程的退出

七、查看结果

在当前路径下会发现生成了一个img文件夹,点击进去就可以看见以title命名的各个文件夹,文件内就是以MD5值命名的图片。

这是一个简单的爬虫,也是我学习爬虫后第一次爬取ajax请求,大家也可以尝试爬取其他网站的图片。

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

简单爬虫Ajax数据爬取——今日头条图片爬取 的相关文章

  • 在二维数组中进行所有可能的组合

    我正在尝试制作具有所有可能组合的 4x4 16 像素黑白图像数组 我制作了以下数组作为模板 template 0 0 0 0 start with all white pixels 0 0 0 0 0 0 0 0 0 0 0 0 然后我想迭
  • 需要根据数据框中的行号应用不同的公式

    我正在努力在数据框中找到某种移动平均值 该公式将根据正在计算的行数而变化 实际场景是我需要计算Z列 Edit 2 以下是我正在使用的实际数据 Date Open High Low Close 0 01 01 2018 1763 95 176
  • virtualenvwrapper 函数在 shell 脚本中不可用

    所以 我再一次制作了一个很棒的 python 程序 它让我的生活变得更加轻松 并节省了大量时间 当然 这涉及到一个 virtualenv 用mkvirtualenvvirtualenvwrapper 的功能 该项目有一个requiremen
  • pandas read_csv 之前预处理数据文件

    我使用 SAP 的数据输出 但它既不是 CSV 因为它不引用包含其分隔符的字符串 也不是固定宽度 因为它具有多字节字符 它是一种 固定宽度 字符 为了将其放入 pandas 我当前读取文件 获取分隔符位置 对分隔符周围的每一行进行切片 然后
  • caffe安装:opencv libpng16.so.16链接问题

    我正在尝试在 Ubuntu 14 04 机器上使用 python 接口编译 caffe 我已经安装了 Anaconda 和 opencvconda install opencv 我还安装了咖啡中规定的所有要求 并更改了注释块makefile
  • 在 python 中发送标头[重复]

    这个问题在这里已经有答案了 我有以下 python 脚本 我想发送 假 标头信息 以便我的应用程序就像 Firefox 一样运行 我怎么能这么做呢 import urllib urllib2 cookielib username passw
  • 我可以同时打开两个 Tkinter Windows 吗?

    可以同时打开2个窗口吗 import tkinter as Tk import random import math root Tk Tk canvas Tk Canvas root background image Tk PhotoIma
  • Discord.py 斜线命令在 cogs 中不起作用

    我正在构建一个不和谐的机器人 并且想要在 cogs 内使用斜杠命令 但这些命令不显示或工作 这是代码 cog guild ids 858573429787066368 861507832934563851 class Slash comma
  • 在多核上运行 python 线程

    我知道Python 2 7不允许在不同的内核上运行多个线程 你需要使用multiprocessing模块以实现某种程度的并发性 我正在看concurrent futuresPython 3 4 中的模块 是否使用ThreadPoolExec
  • 对法语文本进行词形还原[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有一些法语文本需要以某种方式进行处理 为此 我需要 首先 将文本标记为单词 然后对这些单词进行词形还原以避免多次处理相同的词根 据我
  • matplotlib:渲染到缓冲区/访问像素数据

    我想使用 matplotlib 生成的图作为 OpenGL 中的纹理 到目前为止 我遇到的 matplotlib 的 OpenGL 后端要么不成熟 要么已经停止使用 所以我想避免使用它们 我当前的方法是将图形保存到临时 png 文件中 并从
  • 如何在 python 中使用交叉验证执行 GridSearchCV

    我正在执行超参数调整RandomForest如下使用GridSearchCV X np array df features all features y np array df gold standard labels x train x
  • Pygame:有人可以帮我实现双跳吗?

    我知道已经有其他关于此问题的帖子了 但我的运动系统与我发现的有点不同 所以随后我问这个问题 我的运动系统基于一个名为的命名元组Move up left right down 然后就是这个 def update self move block
  • 机器学习的周期性数据(例如度角 -> 179 与 -179 相差 2)

    我使用 Python 进行核密度估计 并使用高斯混合模型对多维数据样本的可能性进行排名 每一条数据都是一个角度 我不确定如何处理机器学习的角度数据的周期性 首先 我通过添加 360 来删除所有负角 因此所有负角都变成了正角 179 变成了
  • Django 1.7:如何使用 html/css 文件作为模板发送电子邮件

    从 Django 1 7 开始 可以send email 使用新参数 html message 不幸的是 没有关于如何使用它的全面指南 新手友好 或者至少我找不到它 我需要使发送的电子邮件变得漂亮 因此 我试图弄清楚如何将我的消息包含到 h
  • 在Python中随机交错2个数组

    假设我有两个数组 a 1 2 3 4 b 5 6 7 8 9 我想将这两个数组交错为变量 c 注意 a 和 b 不一定具有相同的长度 但我不希望它们以确定性的方式交错 简而言之 仅仅压缩这两个数组是不够的 我不想要 c 1 5 2 6 3
  • 如何在类型提示中定义元组或列表的大小

    有没有办法在参数的类型提示中定义元组或列表的大小 目前我正在使用这样的东西 from typing import List Optional Tuple def function name self list1 List Class1 if
  • 本地主机上的 Google App Engine GQL 查询

    我正在 Google App Engine Windows 上的 SDK 版本 1 7 0 上开发一个应用程序 我需要经常测试该应用程序 并且此测试涉及数据存储上的大量 GQL 查询 您可以在 App Engine 管理界面的浏览器中在线运
  • 如何将Python包从旧版本安装到新版本?

    我正在使用 python 3 7 最近在 Linux 中安装了 python 3 8 是否有任何 bash 命令或脚本可以获取 3 7 的所有软件包列表并在 3 8 版本中一一安装 我想避免每个包裹都手工完成 注意 我将它们安装在我的系统中
  • JSONDecodeError:额外数据:Python [重复]

    这个问题在这里已经有答案了 我使用以下代码从文件加载 json file file name obj list with open file as f for json obj in f obj list append loads json

随机推荐

  • 17 Redis缓存更新策略(缓存和数据库更新选择)

    1 先更新数据库 在更新缓存 会有异常 更新完Mysql 发生异常 redis还没有更新 导致redis的是旧数据 下次读取缓存读的是脏数据 2 先删除缓存 在更新数据库 1 缓存已经删了 mysql还在更新中 由于Mysql还在更新中 会
  • java类注释_Java注释,java类注释详解

    一个程序的可读性 关键点就在于注释 下面要给大家讲到的就是Java注释方面的知识 主要会介绍java类注释 类注释一般必须放在所有的 import 语句之后 类定义之前 主要声明该类可以做什么 以及创建者 创建日期 版本和包名等一些信息 下
  • VS2022编译调试FFmpeg

    Git 工具下载 安装直接选择好安装路径 直接下一步到安装完成 配置好工程目录 msvc为编译生成的目标文件的目录 source为源代码目录 进入source目录 通过Git下载FFmpeg git clone https github c
  • 设计模式(三)——装饰模式

    往期地址 设计模式 一 简单工厂模式 设计模式 二 策略模式 本期主题 讲解装饰模式 装饰模式 1 什么是装饰模式 2 实例 2 1 场景 2 2 代码 1 什么是装饰模式 装饰模式是一种结构型设计模式 可以把对象的特殊行为进行封装 从而为
  • ue4单选框设置

    奇怪的是 ue4只有多选框 原来合并了 Style FCoreStyle Get RadioButton 不多说了 放代码 先枚举几个 enum ERadioChoice Radio0 Radio1 Radio2 SHorizontalBo
  • steps_per_epoch=2000,epochs=100之间的区别

    第一种解释 batchsize 中文翻译为批大小 批尺寸 在深度学习中 一般采用SGD训练 即每次训练在训练集中取batchsize个样本训练 iteration 中文翻译为迭代 1个iteration等于使用batchsize个样本训练一
  • 小程序

    文章目录 新建项目并梳理项目结构 配置导航栏效果 配置 tabBar 效果 实现轮播图效果 获取轮播图数据 渲染轮播图页面效果 对轮播图进行美化 实现九宫格效果 获取九宫格数据 渲染九宫格布局 美化九宫格布局 实现图片布局 上拉触底案例 定
  • Lua判断一个对象是否为空,包含userdata

    Lua判断一个对象是否为空 客户端在开发游戏的时候 经常会遇到一个问题 C 传递过来的GameObject已经被销毁了 但是lua这边判断却不是nil 而是一个userdata 那怎么判断一个userdata是否为空呢 可以使用如下代码判断
  • SSH密码暴力破解

    SSH密码暴力破解 1 Hydra 海德拉 hydra 是世界顶级密码暴力密码破解工具 支持几乎所有协议的在线密码破解 功能强大 其密码能否被破解关键取决于破解字典是否足够强大 在网络安全渗透过程中是一款必备的测试工具 1 1指定用户破解
  • 数据结构自考

    设带头结点的单向循环链表的头指针为变量head 则空循环链表的判定条件是 head gt next head 一个具有n个顶点的无向完全图的边数为 n n 1 2 设某有向图有n个顶点 则改有向图对应的邻接表中的表头节点个数为n 若查找每个
  • 使用freemarker生成静态html文件

    一 引入依赖
  • 如何在家里赚钱,分享六个适合普通人长期可做的副业

    当今社会 压力越来越大 工作 家庭 生活等等 方方面面都需要钱 仅靠一份工作赚钱 已经很难满足我们的需求 所以越来越多的人尝试做副业 通过副业增加收入 让生活过得更幸福 常见的副业都是业余学一项技能 通过这项技能来赚钱 这是最保险的副业方式
  • 获取磁盘信息并扫描是否连接移动磁盘之JS版

    昨天弄了一天 扫描U盘是否连接到电脑 的功能 折腾了一天出了个java版和js版 这里记录下JS版本 先说说思路 从浏览器的地址栏打开网页之后 通过onload事件调用ActiveXObject判断U盘是否连接到电脑 若是连接了获取信息显示
  • 数论 费马小定理+快速幂取模

    D Sum Time Limit 1000MS Memory Limit 131072KB 64bit IO Format I64d I64u Submit Status Description Input 2 Output 2 Hint
  • 商用服务器性能,安全与性能兼顾的商用服务器推荐

    数据作为企业生存之本 如果没有好的商用服务器为其安全性保驾护航 企业就会变成无本之木 而在众多商用服务器推荐中 能将稳定性能 快速处理 高安全性等优点集一身的当属全球销量独占鳌头的戴尔14代PowerEdge服务器 作为现代化数据中心的基石
  • 关于“使用rand()产生的随机数每次得到的结果相同”的问题

    之前使用rand 产生随机数出现了一个怪问题 一直没能理解 初次出现的随机数数列是1111 5556 3543 6434 3245 再次运行 产生的结果仍然是1111 5556 3543 6434 3245 再运行 仍然是1111 5556
  • apt命令

    在基于 Debian 的 Linux 发行版中 有各种工具可以与 APT 进行交互 以方便用户安装 删除和管理的软件包 apt get 便是其中一款广受欢迎的命令行工具 另外一款较为流行的是 Aptitude 这一命令行与 GUI 兼顾的小
  • 利用python进行图像视觉基础练习

    练习内容为 1 对于图像进行均值滤波和中值滤波 2 对于图像的第二个波段 进行灰度图自适应均衡化 输出为单波段影像 3 对于图像的第三个波段进行阈值处理和自适应阈值处理 输出为单波段影像 4 对于图像先进行二值化 再进行两种形态学处理 开运
  • iocp之简单实现

    一 步骤 二 代码 1 头文件 include
  • 简单爬虫Ajax数据爬取——今日头条图片爬取

    一 Ajax简介 什么是Ajax Ajax 即 Asynchronous Javascript And XML 异步 JavaScript 和 XML 是指一种创建交互式网页应用的网页开发技术 通过在后台与服务器进行少量数据交换 Ajax