爬取Ajax类型数据

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_38038143/article/details/82152483

什么是Ajax?

简单来说就是浏览网页时该页内容浏览完后, 只需要向下滑动, 自动出现新的内容, 而不需要刷新页面. 如浏览新浪微博. 爬取Ajax类型数据, 需要用程序模拟Ajax向服务器发送请求, 根据响应内容得到我们想要的数据.


本文以今日头条为例, 作者使用Google浏览器

目的: 搜索街拍,爬取图片。

首先登录今日头条搜索街拍(https://www.toutiao.com/search/?keyword=%E8%A1%97%E6%8B%8D), 切换到如下图界面:
这里写图片描述

查看详细信息, 选中?offset=0&format=json…

当向下滑动鼠标时会发现, 会多出文件, 如下图
这里写图片描述
这些就是Ajax请求, 可以发现规律, 这些请求的区别仅仅在于offset值的不同, 并且以20为倍值.

分析请求的内容, 如下图

这里写图片描述
可以发现只有 image_list 为图片的地址, 因此我们需要获取到该内容. 除此之外, 有的不拥有 image_list选项, 因此在编写代码时需要注意判断.


代码:

import requests
from urllib.parse import urlencode
import os

"""
    爬去ajax网站信息
    以今日头条为例
    搜索街拍, 下载图片
"""

base_url = 'https://www.toutiao.com/search_content/?'
headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36'
}
offset_start = 1
offset_end = 2

def get_page(offset):
    """
        根据偏移量获取网页
    """
    global headers
    # url请求参数
    params = {
        'offset': offset,
        'format': 'json',
        'keyword': '街拍',
        'autoload': 'ture',
        'count': '20',
        'cur_tab': '1',
        'from': 'search_tab'
    }
    # 拼接url
    url = base_url + urlencode(params)

    # 请求url
    try:
        response = requests.get(url, headers=headers)
        if response.status_code == 200: # 请求成功
            return response.json()
    except response.ConnectionError as e:
        return None

def get_image(json_text):
    """
        从json类型的文字中提取出图片地址
    """
    data = json_text.get('data')
    # json中是否存在data数据
    if data:
        for item in data:
            if item.get('image_list') is None: # 判断是否存在图片链接
                continue
            title = item.get('title')
            images = item.get('image_list') # 获取该页面的所有图片url
            print(title)
            for image in images:
                yield {
                    'image': 'https:' + image.get('url'),
                    'title': title
                }

def down_save_image(items):
    """下载图片并保存"""
    global headers
    dirname = items.get('title')
    # 如过不存在标题目录则创建
    if not os.path.exists(dirname):
        os.mkdir(dirname)
    try:
        response = requests.get(items['image'], headers=headers)
        if response.status_code == 200:
            # 图片以其url/最后为名
            image_name_temp = str(items.get('image')).split('/')
            print(items.get('image'))
            imagename = image_name_temp[len(image_name_temp)-1]
            # 拼接图片名称
            image_path = '{dirname}/{imagename}.{suffix}'.format(dirname=dirname, imagename=imagename, suffix='jpg')
            # 保存图片到本地
            if not os.path.exists(image_path):
                with open(image_path, 'wb') as f:
                    f.write(response.content)
    except response.ConnectionError as e:
        print('Failed to download or save image')

def main():
    global offset_start
    global offset_end
    # 根据起始页和终止页爬取
    for offset in ([x *20 for x in range(offset_start, offset_end+1)]):
        json = get_page(offset)
        items = get_image(json)
        for item in items:
            down_save_image(item)

if __name__ == '__main__':
    main()

结果展示:

这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_38038143/article/details/82152483
今日推荐