爬取今日头条街拍美图

爬取今日头条街拍美图

一、项目需求

1. 抓取今日头条街拍图片,并将每组图片储存到本地。

2. 图片格式存储为jpg

3. 每组图片用一个独立的文件夹储存

二、项目分析

目标URL为:https://www.toutiao.com/search/?keyword=街拍,如下截图:

 这里可以发现,目标URL是由ajax加载,然后用JavaScript渲染出来的。请求的参数有offset、format、keyword、autoload、count、cur_tab 和 from ,除了offset参数以外,其余的都是固定的参数(可以自行推理,拖动鼠标滚轮让下走则会继续发送ajax请求,再打开新的请求发现参数offset的值为20,第三个请求的offset值为40,也就是说,每次请求20组数据,其余的参数均不变)。再通过Preview选项卡观察data字段,会发现我们需要的数据就在这里面,以其中的一个为例:

我们需要的图片url就在image_list中,而这组图片的标题则在title字段中:

三、项目源码

import requests
from urllib.parse import urlencode
import os
from hashlib import md5
from multiprocessing.pool import Pool


def get_page(offset):
    """加载一个ajax请求的结果"""
    params = {
        'offset':offset,
        'format':'json',
        'keyword':'街拍',
        'autoload':'true',
        'count':'20',
        'cur_tab':'3',
        'from': 'gallery'
    }
    url = 'http://www.toutiao.com/search_content/?' + urlencode(params)
    try:
        response = requests.get(url)
        if response.status_code == 200:
            return response.json()
    except requests.ConnectionError:
        return None


def get_images(json):
    """解析方法,提取每条数据的image_list字段中的图片链接,将图片链接和所属标题一同返回"""
    if json.get('data'):
        for item in json.get('data'):
            title = item.get('title')
            images = item.get('image_list')
            if images:
                for image in images:
                    yield {
                        'image':image.get('url'),
                        'title':title
                    }


def save_image(item):
    """保存图片方法,根据item中的title来创建文件夹,然后请求图片链接,获取图片的二进制数据,并写入文件。图片命名使用了md5"""
    if not os.path.exists(item.get('title')):
        os.mkdir(item.get('title'))
    try:
        local_image_url = item.get('image')
        new_image_url = local_image_url.replace('list','large')
        response = requests.get('http:' + new_image_url)
        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 Download',file_path)
    except requests.ConnectionError:
        print('Failed to Save Image')


def main(offset):
    """主函数"""
    json = get_page(offset)
    for item in get_images(json):
        print(item)
        save_image(item)


GROUP_START = 1
GROUP_END = 5

if __name__ == '__main__':
    pool = Pool()
    groups = ([x * 20 for x in range(GROUP_START,GROUP_END + 1)])
    pool.map(main,groups)
    pool.close()
    pool.join()

猜你喜欢

转载自www.cnblogs.com/jonas-von/p/9198500.html