Python爬虫:爬取今日头条“街拍”图片(修改版)

前言

在参考《Python3网络爬虫开发实战》学习爬虫时,练习项目中使用 requests ajax 爬取今日头条的“街拍”图片,发现书上的源代码有些已经不适合现在了,报了一些错(毕竟网站也在不停变化)。

变化、报错及解决方法

  1. 爬取的 ajax 结果中 data 为 None,原因是在头条网站搜索“街拍”后多了个图片验证。

    解决方法:使用 headers 加上Cookie。

  2. 第54行 for image in images 报错TypeError:‘NoneType’ object is not iterable(类型错误:“NoneType”对象不是可迭代的) ,原因是爬取结果中有些 image_list 为None。

    解决方法:在 for 遍历前,加上 if images: 判断是否为None。

  3. 书上源代码是直接把图片存放在当前 py 文件所在目录下,太不美观了。

    解决方法:新建 images 文件夹,在爬取开始前提前切换到图片存放目录 images ,在第93行切换 os.chdir(‘images’) ,之后新建的图片文件夹都是在 images 文件夹下面。注意要在爬取开始前切换,不然会出现多次切换的报错。

完整代码

import requests
from urllib.parse import urlencode
import os
from hashlib import md5

headers = {
    'cookie': '__tasessionId=ampozol5g1563806844189; tt_webid=671649' +
    '9234256455175; WEATHER_CITY=%E5%8C%97%E4%BA%AC; UM_distinctid=16c' +
    '1a26e5e12df-040ada0c1d8081-c343162-100200-16c1a26e5e428c; CNZZDAT' +
    'A1259612802=945869726-1563806204-https%253A%252F%252Fwww.google.c' +
    'om%252F%7C1563806204; tt_webid=6716499234256455175; csrftoken=46' +
    'a41d4141000920aea9354904736a2d; s_v_web_id=2b8f7242614ce9f3dd7cbf' +
    '26d932530d',
    'host': 'www.toutiao.com',
    'referer': 'https://www.toutiao.com/search/?keyword=%E8%A1%97%E6%8B%8D',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit' +
    '/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36',
    'x-requested-with': 'XMLHttpRequest'
}


def get_page(offset):
    params = {
        'aid': '24',
        'app_name': 'web_search',
        'offset': offset,
        'format': 'json',
        'keyword': '街拍',
        'autoload': 'true',
        'count': '20',
        'en_qc': '1',
        'cur_tab': '1',
        'from': 'search_tab',
        'pd': 'synthesis',
        'timestamp': '1563782026489'
    }
    url = 'https://www.toutiao.com/api/search/content/?' + urlencode(params)
    print(url)
    try:
        response = requests.get(url, headers=headers)
        if response.status_code == 200:
            print('suc_1')
            return response.json()
    except requests.ConnectionError:
        return None


def get_images(json):
    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:
                    print('suc_2')
                    yield {
                        'image': image.get('url'),
                        'title': title
                    }
    else:
        print('data is none')


def save_image(item):
    # 判断在当前目录下是否存在以参数为名的文件夹
    if not os.path.exists(item.get('title')):
        os.mkdir(item.get('title'))     # 在当前目录下创建以参数为名的文件夹
    try:
        print('suc_3')
        response = requests.get(item.get('image'))
        if response.status_code == 200:
            # md5摘要算法(哈希算法),通过摘要算法得到一个长度固定的数据块。
            # md5() 获取一个md5加密算法对象
            # hexdigest() 获取加密后的16进制字符串。
            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)
    except requests.ConnectionError:
        print('Failed To Save Image')


def main(offset):
    json = get_page(offset)
    for item in get_images(json):
        save_image(item)


if __name__ == '__main__':
    groups = [x * 20 for x in range(1, 5)]
    os.chdir('images')    # 提前切换到图片存放目录
    for val in groups:
        main(val)

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值