当前位置: 首页 > article >正文

360图片爬虫|批量爬取图片

 360图片爬虫逆向,批量爬取360图片所有分类下的图片,结尾附完整代码

一、抓包分析 

1.1思路分析

GET请求 https://image.so.com/c?ch=art&t1=1780

 通过分析可以知道360图片的链接有两个参数cht1

ch参数表示为下方图片红色一栏的一级分类,如图所示的art表示艺术分类

t1参数表示为下方图片蓝色一栏的二级分类,如图所示的1780表示艺术名家欣赏

当我们查看抓包到的

https://image.so.com/z?a=filter&ch=art

的数据时 ,可以发现响应中有其对应的所有二级分类的中文名以及cat_id

cat_id就是开头的t1

因为一级分类较少,所以可以直接使用字典固定即可

categories = {
'art': '艺术',
'wallpaper': '壁纸',
'design': '设计',
'car': '汽车',
'food': '食物',
'home': '家具',
'pet': '宠物'
}

所以通过循环请求

https://image.so.com/z?a=filter&ch=art 

就可以得到所有的二级分类对应的id和中文名

 1.2爬取图片

GET请求 https://image.so.com/zjl?sn=0&ch=art&t1=200

sn——图片批次每次30张,0是这个分类下的1-30张图片,sn每次加30 比如sn=0.接下来就是sn=30

ch——一级分类字典

t1——二级分类id

可以看到sn=0时,该分类下的30张图像的信息

title——图像标题

qhimg_url——图像下载链接

通过分类获取好t1对应的id之后,再通过循环GET请求https://image.so.com/zjl?sn=0&ch=art&t1=200 获取标题和图像即可实现批量爬取360图片

二、代码实现 

代码概要

tool.py  —— 负责爬取各二级分类的id以及分类名称,效果如下

image.py —— 根据tool.py得到的id批量下载图片 ,效果如下

2.1分类id获取代码  tool.py

import os
import requests
import json
import csv

def fetch_and_save_categories(url, params, headers, output_file):
    # 发送GET请求
    response = requests.get(url, headers=headers, params=params)

    # 检查响应状态码
    if response.status_code == 200:
        # 解析JSON响应
        data = response.json()

        # 检查是否存在 'result' 键
        if 'result' in data and 'category' in data['result']:
            categories = data['result']['category']

            # 提取并写入CSV文件
            def extract_categories(categories):
                result = []
                result.append({'cat_id': categories['cat_id'], 'cat_name': categories['cat_name']})
                if '_child' in categories:
                    for child in categories['_child']:
                        result.extend(extract_categories(child))
                return result

            extracted_data = extract_categories(categories)

            # 写入CSV文件
            with open(output_file, 'w', newline='', encoding='utf-8') as file:
                csv_writer = csv.writer(file)
                csv_writer.writerow(['cat_id', 'cat_name'])
                for item in extracted_data:
                    csv_writer.writerow([item['cat_id'], item['cat_name']])
            print(f"数据已保存到 {output_file} 文件中")
        else:
            print("响应中没有找到预期的 'category' 键")
    else:
        print(f"请求失败,状态码: {response.status_code}")

# 请求的不同ch参数值
categories = {
    'art': '艺术',
    'wallpaper': '壁纸',
    'design': '设计',
    'car': '汽车',
    'food': '食物',
    'home': '家具',
    'pet': '宠物'
}

url = 'https://image.so.com/z'
headers = {
    'Host': 'image.so.com',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:126.0) Gecko/20100101 Firefox/126.0',
    'Accept': 'application/json, text/plain, */*',
    'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
    'Accept-Encoding': 'gzip, deflate, br, zstd',
    'Connection': 'keep-alive',
    'Referer': 'https://image.so.com/c?ch=art',
    'Cookie': 'QiHooGUID=2C41DF4F85C67A33C6AE6159D21836EE.1718195055756; __guid=16527278.2902233284592428000.1718195056738.8062; opqopq=8141981f1c97476ba46d47ebcc40c064.1718425129; _S=5975bd6fe122a862f99b36b09c3bf2dd',
    'Sec-Fetch-Dest': 'empty',
    'Sec-Fetch-Mode': 'cors',
    'Sec-Fetch-Site': 'same-origin',
    'TE': 'trailers'
}

# 确保数据目录存在
data_dir = './data/title'
if not os.path.exists(data_dir):
    os.makedirs(data_dir)

# 循环不同的ch参数值
for ch, category_name in categories.items():
    params = {
        'a': 'filter',
        'ch': ch
    }
    output_file = os.path.join(data_dir, f"{ch}_categories.csv")
    fetch_and_save_categories(url, params, headers, output_file)

2.2图像下载代码  image.py

import os
import requests
import re
import csv
import time
import random
import urllib3

# 禁用不安全请求警告
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)


def fetch_and_save_images(url, params, headers, save_folder):
    print('****************'+url+'************')
    print('****************' + str(params) + '************')
    # 创建保存文件夹
    if not os.path.exists(save_folder):
        os.makedirs(save_folder)

    # 发送GET请求,忽略SSL验证
    try:
        response = requests.get(url, headers=headers, params=params, verify=False)
    except requests.exceptions.RequestException as e:
        print(f"请求失败: {e}")
        return

    # 检查响应状态码
    if response.status_code == 200:
        # 解析JSON响应
        data = response.json()
        print(str(data))
        # 检查是否存在 'list' 键
        if 'list' in data:
            # 获取所有 'imgurl' 和 'title'
            for item in data['list']:
                img_url = item['qhimg_url']
                title = item['title']
                # 清理标题以便用作文件名
                clean_title = re.sub(r'[\\/*?:"<>|]', "_", title)

                # 下载图片
                try:
                    img_response = requests.get(img_url, stream=True)
                    if img_response.status_code == 200 and 'image' in img_response.headers['Content-Type']:
                        file_path = os.path.join(save_folder, f'{clean_title}.jpg')
                        with open(file_path, 'wb') as handler:
                            for chunk in img_response.iter_content(1024):
                                handler.write(chunk)
                        print(f"图片已保存到: {file_path}")

                        # 设置下载间隔时间
                    else:
                        print(f"下载图片失败: {img_response.status_code}, 图片URL: {img_url}, 内容类型: {img_response.headers['Content-Type']}")
                except requests.exceptions.RequestException as e:
                    print(f"下载图片失败: {e}, 图片URL: {img_url}")
    else:
        print(f"请求失败,状态码: {response.status_code}")


def get_categories_from_csv(csv_file):
    categories = []
    with open(csv_file, 'r', encoding='utf-8') as file:
        csv_reader = csv.reader(file)
        next(csv_reader)  # 跳过标题行
        for row in csv_reader:
            categories.append({'cat_id': row[0], 'cat_name': row[1]})
    return categories


# 请求的不同ch参数值
categories_dict = {
    'art': '艺术',
    'wallpaper': '壁纸',
    'design': '设计',
    'car': '汽车',
    'food': '食物',
    'home': '家具',
    'pet': '宠物'
}



# 确保数据目录存在
data_dir = './data'
if not os.path.exists(data_dir):
    os.makedirs(data_dir)

# 循环不同的ch参数值
for ch, category_name in categories_dict.items():
    csv_file = f'./data/title/{ch}_categories.csv'
    headers = {
        'Host': 'image.so.com',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:126.0) Gecko/20100101 Firefox/126.0',
        'Accept': 'application/json, text/plain, */*',
        'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
        'Accept-Encoding': 'gzip, deflate, br, zstd',
        'Connection': 'keep-alive',
        'Referer': f'https://image.so.com/c?ch={ch}',
        'Cookie': 'QiHooGUID=2C41DF4F85C67A33C6AE6159D21836EE.1718195055756; __guid=16527278.2902233284592428000.1718195056738.8062; opqopq=8141981f1c97476ba46d47ebcc40c064.1718425129; _S=5975bd6fe122a862f99b36b09c3bf2dd',
        'Sec-Fetch-Dest': 'empty',
        'Sec-Fetch-Mode': 'cors',
        'Sec-Fetch-Site': 'same-origin',
        'TE': 'trailers'
    }
    # 获取所有类别信息从CSV文件
    categories = get_categories_from_csv(csv_file)

    # 创建保存图片的基础目录
    base_image_dir = os.path.join(data_dir, 'images',ch)
    if not os.path.exists(base_image_dir):
        os.makedirs(base_image_dir)

    # 遍历所有类别并下载图片
    for category in categories:
        cat_id = category['cat_id']
        cat_name = category['cat_name']
        params = {
            'sn': '0',
            'ch': ch,
            't1': cat_id
        }
        save_folder = os.path.join(base_image_dir, cat_name)
        fetch_and_save_images('https://image.so.com/zjl', params, headers, save_folder)

http://www.kler.cn/a/571969.html

相关文章:

  • Vue05
  • QT-自定义参数设计框架软件
  • 爬虫(持续更新ing)
  • wordpress子分类调用父分类名称和链接的3种方法
  • Android 系统开发的指导文档
  • 奇安信天擎面试题
  • 未来经济范式争夺战:AR眼镜为何成为下一代交互终端的制高点?
  • 【TCP/IP协议栈】2. 网络接口层协议(以太网、令牌环、PPP 等)
  • 【STM32】TIM输入捕获-学习笔记
  • 2025年能源工作指导意见
  • 【Unity】鼠标在某区域悬停触发文本框,移开关闭文本框
  • 蔡司智锐系列眼镜:智能动态护眼,畅享数字化生活
  • doris: Hive
  • 通俗的方式解释“零钱兑换”问题
  • mysql空间占用
  • Git基本命令索引
  • 【音视频】音频基础
  • SQLite Alter 命令详解
  • android13打基础:控件datepicker
  • 【每日学点HarmonyOS Next知识】手写电子签名、瀑布流布局获取字符串高度、WaterFlow崩溃、Web滑动问题