我的爬虫 之 爬今日头条街拍图片

本文介绍了一种爬取今日头条网站上街拍图片的方法。通过分析网站请求方式和页面渲染机制,利用Python爬虫技术抓取图片链接并保存。

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

          近日学习了python 爬虫方面的内容 ,决定实战——爬今日头条的街拍图片

  首先先分析今日头条的请求方式,进入https://www.toutiao.com  F12 搜索街拍

   

查看当前请求 https://www.toutiao.com/search/?keyword=街拍 打开network 中的 preview 查看相应源码,发现并没有关于图片

信息的内容 ,于是初步判断页面是由js渲染的,打开xhr(ajax请求)果不其然有个请求

查看data中的属性发现title和标题一致说明数据是由ajax加载的 ,进过分析data里面的数据并未有5张图片的url

只有一个image_url 里面只有四张已展示出来的图片,所以需要进入 article_url  详细页面去爬

 

 

查看 https ://www.toutiao.com/a6596072828330574344/ 请求头,会发现所有的 图片都在gallery里面

返回到 https://www.toutiao.com/search/?keyword=街拍 查看请求头 会发现 url里面有很多参数 offset format keyword autoload count cur_tabfrom  

继续往下加载 会发现多个一个ajax 请求且 offset=20 其他参数为改变 说明offset是控制数量的

分析完毕,以下是代码:

        首先获取 josn数据

import requests
from urllib.parse import urlencode
def get_page(offset,keyword):
    #https://www.toutiao.com/search_content/?offset=20&format=json&keyword=%E8%A1%97%E6%8B%8D&autoload=true&count=20&cur_tab=1&from=search_tab
    params = {
        'offset':offset,
        'format':'json',
        'keyword':keyword,
        'autoload':'true',
        'count':'20',
        'cur_tab':'1',
        'from':'search_tab'
    }
    url = 'https://www.toutiao.com/search_content/?'+urlencode(params)
    try:
        response = requests.get(url)
        if response.status_code == 200:
            return response.json()
    except requests.ConnectionError as e:
        print(e)
        return None

在得到json数据后 需要获取 获取数据data里面的 article_url和title

#解析json,获取title,和url列表
def get_items(json):
    if json.get('data'):
        for item in json.get('data'):
            title  =item.get('title')
            #文章url
            article_url = item.get('article_url')
            #获取图片集
            if article_url != None:
                urls = get_images(article_url)
                for url in urls:
                    yield {
                        'title':title,
                        'url':url
                    }

在获取了详细页面的url后 需要页面里的所有图片的url, 在上面解析可以知道我们要获取的图片的url都在gallery,这里需要通过正则来获取gallery里面的,再发出请求时需要伪装自己的主机环境 ,这里我有些不懂(我在网页解析的result.group(1) 本身是一个json格式,但是在json.loads(result.group(1)) 这个语句会报错 json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1) ,我把解析的语句放在交互环境是没有问题的) 所以为了解决这个问题我对数据做了解码操作 codecs.getdecoder('unicode_escape')(result.group(1))  codecs 可以参考 python模块之codecs 编码问题参考python3中的unicode_escape 解码后 转换json  

数据如下:

由图片url可知 sub_image ,sub_image 中 由url 和 url_list ,分析可知url_list 里面的url指向的是同一张图片,所以我们获取url即可

代码如下:

import requests
import re
import codecs
import json
def get_images(url):
    headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36     (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36',
    }
    #需要头伪装自己
    response = requests.get(url,headers=headers)
    # 使用beautifulSoup 解析
    #gallery: JSON.parse("{\"count\":7,\"sub_images\":[{\"url\":\"http:\\/\\/p99.pstatp.com\\/origin\\/pgc-image\\/15356770660120337f0438e\",\...

    image_pattern = re.compile(r'gallery: JSON.parse\("(.*?)"\)',re.S)
    #print(response.text)
    result = re.search(image_pattern,response.text)
    #print(result.group(1))
    #解码
    if result !=None:
        data_str = codecs.getdecoder('unicode_escape')(result.group(1))[0]
        data_json = json.loads(data_str)
        if 'sub_images' in data_json.keys():
            sub_images = data_json.get('sub_images')
            urls = [item.get('url') for item in sub_images]
            return urls
    return []

在得到了图片url后我们需要将图片保存已标题为目录,一个目录为一图集  代码如下:

import os
import requests
headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36',
}
#保存图片
def save_image(item):
    if not os.path.isdir(item.get('title')):
        os.mkdir(item.get('title'))
    #加头伪装
    try:
        res = requests.get(item.get('url'),headers=headers)
        if res.status_code == 200:
            file_path = '{0}/{1}.{2}'.format(item.get('title'), md5(res.content).hexdigest(), 'jpg')
            with open(file_path,'wb') as f:
                f.write(res.content)
    except requests.ConnectionError:
        print('未读取')

 在整合代码:

   

from multiprocessing.pool import Pool
def main(offset):
    for item in get_items(get_page(offset,'街拍')):
        save_image(item)

GROUP_START = 1
GROUP_END = 20
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()

   end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值