进阶爬虫:今日头条街拍美图

本文介绍了一种从今日头条网站抓取街拍美图的爬虫技术,利用Ajax和JSON数据,通过Python实现图片的下载、解析及保存至本地和MongoDB数据库的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关键字: json 爬虫 MongoDB

GitHub:https://github.com/utopianist/JiePai


前言

今日我们在 今日头条 网站上爬取 街拍美图

今日头条 的数据都是用 Ajax 技术加载渲染完成,打开 今日头条 页面源码,连一根鸡毛都没有。

html.gif

在我们爬虫界,按照 ‘可见即可爬’ 的原则, 所谓的 Ajax 就是 ’换一个页面‘ 爬取我们想要爬取的资源。

换的那个页面,有时是 XHR 文件,有时是 HTML 文件。

目标站点分析

F12审查页面元素。

toutiao.png

我们需要的资源全部在这个 URL 下。

获取JSON数据

def getPage(offset):
    params = {
        'offset': offset,
        'format': 'json',
        'keyword': '街拍',
        'autoload': 'true',
        'count': '20',
        'cur_tab': '3',
        'from': 'gallery',
    }
    url = 'https://www.toutiao.com/search_content/?' + urlencode(params)
    try:
        r = requests.get(url)
        if r.status_code == 200:
            return r.json()
    except requests.ConnectionError:
        return ""
urllib.parse.urlencode()

转换映射对象或两个元素的元组,其可以包含的序列 strbytes 对象。如若是字符串,则结果是由 ‘&’ 分隔的 key=value 的系列队。

解析Json数据

def getImage(json):
    data = json.get('data')
    for item in data:
        title = item.get('title')
        image_list = item.get('image_list')
        if image_list:
            for item in image_list:
                yield{
                    'title': title,
                    'image': item.get('url')
                }

保存图片

def saveImage(item):
    img_path = 'img' + os.path.sep + item.get('title')
    if not os.path.exists(img_path):
        os.makedirs(img_path)
    local_image_url = item.get('image')
    new_image_url = local_image_url.replace('list', 'large')
    r = requests.get('http:' + new_image_url)
    if r.status_code == 200:
        file_path = img_path + os.path.sep +'{0}.{1}'.format(md5(r.content).hexdigest(), 'jpg')
        if not os.path.exists(file_path):
            with open(file_path, 'wb') as f:
                f.write(r.content)

在官方文档中描述 hexdigest() 函数的一段话:

At any point you can ask it for the digest of the concatenation of the strings fed to it so far using the digest() or hexdigest() methods.

大概意思是:

到目前为止,hexdigest() 和 digest() 函数能满足你把一串字符串的组合物变成一段摘要的需要。

官方文档:

https://docs.python.org/2/library/hashlib.html

保存到MongDB

def saveToMongo(item):
    if db[MONGO_TABLE].insert(item):
        print('储存到MONGODB成功', item)
    return False

主函数和进程池

def main(offset):
    json = getPage(offset)
    for item in getImage(json):
        saveImage(item)
        saveToMongo(item)

if __name__ == '__main__':
    pool = Pool()
    groups = [x * 20 for x in range(2)] #爬取五页
    pool.map(main, groups)
    pool.close() #关闭进程池(pool),使其不在接受新的任务
    pool.join() #主进程阻塞等待子进程的退出

pool 对象调用 join() 方法会让主进程等待所有子进程自行完毕,调用 join() 之前必须先调用 close() ,让其不再接受新的 Process 了。

总结

主要关注如何下载和解析 Json数据。

公众号内输出 ‘崔佬视频’ 获取崔庆才大佬的《Python3WebSpider》全套视频。

全码

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

MONGO_URL = 'localhost'
MONGO_DB = 'toutiao'
MONGO_TABLE = 'toutiao' #数据集合Collection

client = pymongo.MongoClient(MONGO_URL)  # MongoClient 对象,并且指定连接的 URL 地址
db = client[MONGO_DB] #要创建的数据库名

def getPage(offset):
    params = {
        'offset': offset,
        'format': 'json',
        'keyword': '街拍',
        'autoload': 'true',
        'count': '20',
        'cur_tab': '3',
        'from': 'gallery',
    }
    url = 'https://www.toutiao.com/search_content/?' + urlencode(params)
    try:
        r = requests.get(url)
        if r.status_code == 200:
            return r.json()
    except requests.ConnectionError:
        return ""

def getImage(json):
    data = json.get('data')
    for item in data:
        title = item.get('title')
        image_list = item.get('image_list')
        if image_list:
            for item in image_list:
                yield{
                    'title': title,
                    'image': item.get('url')
                }

def saveImage(item):
    img_path = 'img' + os.path.sep + item.get('title')
    if not os.path.exists(img_path):
        os.makedirs(img_path)
    local_image_url = item.get('image')
    new_image_url = local_image_url.replace('list', 'large')
    r = requests.get('http:' + new_image_url)
    if r.status_code == 200:
        file_path = img_path + os.path.sep +'{0}.{1}'.format(md5(r.content).hexdigest(), 'jpg')
        if not os.path.exists(file_path):
            with open(file_path, 'wb') as f:
                f.write(r.content)

def saveToMongo(item):
    if db[MONGO_TABLE].insert(item):
        print('储存到MONGODB成功', item)
    return False

def main(offset):
    json = getPage(offset)
    for item in getImage(json):
        saveImage(item)
        saveToMongo(item)

if __name__ == '__main__':
    pool = Pool()
    groups = [x * 20 for x in range(2)] #爬取五页
    pool.map(main, groups)
    pool.close() #关闭进程池(pool),使其不在接受新的任务
    pool.join() #主进程阻塞等待子进程的退出

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值