鱼C论坛

 找回密码
 立即注册
查看: 1538|回复: 6

[已解决]关于多线程保存图片的半异常

[复制链接]
发表于 2020-7-23 15:50:16 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
上代码
# 导包
import requests
from time import sleep
import os
import threading
import parsel

if not os.path.exists('image'):
    os.mkdir('image')

# base_url = 'https://anime-pictures.net/pictures/view_posts/0?lang=en'

headers = {
    'User-Agent':
        'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36'
}


def get(url, headers):
    '''请求数据'''
    response = requests.get(url, headers)
    html_data = response.text
    return html_data


def parsel_data(html_data):
    '''筛选数据'''
    selector = parsel.Selector(html_data)
    result_list = selector.xpath('//span[@class="img_block_big"]')

    for result in result_list:
        image_url = result.xpath('./a/picture/source/img/@src').extract_first()
        image_id = result.xpath('./a/picture/source/img/@id').extract_first()

        img_url = 'https:' + image_url  # 手动拼url

        all_title = img_url
        img_name = image_id + '.' + img_url.split('.')[-1]

        img_data = requests.get(url=all_title, headers=headers).content

        yield all_title, image_id, img_data, img_name


def save(all_title, image_id, img_data,img_name):
    '''保存数据'''
    try:
        with open('image\\' + img_name, mode='wb') as f:
            print('保存成功:', image_id)
            f.write(img_data)

    except:
        pass
        print('保存失败:', image_id, '(|・ω・` ))')


def start_save(base_url):
    html_data = get(url=base_url, headers=headers)
    for image_data in parsel_data(html_data):
        all_title = image_data[0]  # url https://xxxxxxxxxx...
        img_id = image_data[1]  # ID
        img_data = image_data[2]  # 数据
        img_name = image_data[3] #文件名
        save(all_title=all_title, image_id=img_id, img_data=img_data,img_name = img_name)
        sleep(5)

def main(page):
    for page in range(0, page + 1):
        print('###############正在下载第{}页数据###############'.format(page))
        base_url = 'https://anime-pictures.net/pictures/view_posts/0?lang=en'.format(page)
        if page>0:
            print('休息哈|ू・ω・` )')
            sleep(2)
        my_thread = threading.Thread(target=start_save, args=(base_url,)) #启动多线程
        my_thread.setDaemon(True)
        my_thread.start()
        

if __name__ == '__main__':
    lock = threading.RLock()

    main(6300)




异常,这个异常很奇怪
他一直显示保存成功 但是 实际的文件夹之保存了几张而已
最佳答案
2020-7-24 10:56:13
问题已解决,三十秒内下载了上千张图片。
请看代码:
# 导包
import requests
from time import sleep
import os
import threading
import parsel
import random

if not os.path.exists('image'):
    os.mkdir('image')

# base_url = 'https://anime-pictures.net/pictures/view_posts/0?lang=en'

headers = {
    'User-Agent':
        'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36'
}


def get(url, headers):
    '''请求数据'''
    response = requests.get(url, headers)
    html_data = response.text
    return html_data


def parsel_data(html_data):
    '''筛选数据'''
    selector = parsel.Selector(html_data)
    result_list = selector.xpath('//span[@class="img_block_big"]')

    for result in result_list:
        image_url = result.xpath('./a/picture/source/img/@src').extract_first()
        image_id = result.xpath('./a/picture/source/img/@id').extract_first()

        img_url = 'https:' + image_url  # 手动拼url

        all_title = img_url
        img_name = image_id + '.' + img_url.split('.')[-1]

        img_data = requests.get(url=all_title, headers=headers).content

        yield all_title, image_id, img_data, img_name


def save(all_title, image_id, img_data,img_name):
    '''保存数据'''
    try:
        with open('image\\' + str(random.randint(0,1000000)) + os.path.splitext(img_name)[1], mode='wb') as f:
            print('保存成功:', image_id)
            f.write(img_data)
    except:
        print('保存失败:', image_id, '(|・ω・` ))')


def start_save(base_url):
    html_data = get(url=base_url, headers=headers)
    for image_data in parsel_data(html_data):
        all_title = image_data[0]  # url https://xxxxxxxxxx...
        img_id = image_data[1]  # ID
        img_data = image_data[2]  # 数据
        img_name = image_data[3] #文件名
        save(all_title=all_title, image_id=img_id, img_data=img_data,img_name = img_name)            

def main(page):
    for page in range(0, page + 1):
        print('###############正在下载第{}页数据###############'.format(page))
        base_url = 'https://anime-pictures.net/pictures/view_posts/0?lang=en'.format(page)
        if page>0:
            print('休息哈|ू・ω・` )')
            sleep(2)

        my_thread = threading.Thread(target=start_save, args=(base_url,)) #启动多线程
        my_thread.setDaemon(True)
        my_thread.start()

        

if __name__ == '__main__':
    lock = threading.RLock()
    main(6300)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-7-23 23:00:22 | 显示全部楼层
可以用主线程专门负责下载数据并用一个全局变量列表保存,创建一个子线程专门用来保存文件。
这样就不会影响下载速度而且因为只用一个线程在保存文件所以不会出现 IO 丢失的现象。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-7-24 06:24:36 | 显示全部楼层
nahongyan1997 发表于 2020-7-23 23:00
可以用主线程专门负责下载数据并用一个全局变量列表保存,创建一个子线程专门用来保存文件。
这样就不会影 ...

我把每一个函数都上过一次锁 结果都没用 说白点就是我不知道他的资源竞争哪里
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-7-24 07:33:38 | 显示全部楼层
除了子线程函数其他函数上锁没有任何用处,推荐按我的方法修改一下程序,不影响下载速度只影响保存速度,也不会慢多少。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-7-24 07:52:06 | 显示全部楼层
nahongyan1997 发表于 2020-7-24 07:33
除了子线程函数其他函数上锁没有任何用处,推荐按我的方法修改一下程序,不影响下载速度只影响保存速度,也 ...

我造诣浅薄 只会使用线程最表层的 还请大佬举个例子(听不懂大佬讲的子线程和IO
)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-7-24 08:56:17 | 显示全部楼层
本帖最后由 nahongyan1997 于 2020-7-24 09:03 编辑

主线程里用 threading 开的线程就是子线程,IO 就是 input,output。

写文件就是 文件 Input,也就是 I 。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-7-24 10:56:13 | 显示全部楼层    本楼为最佳答案   
问题已解决,三十秒内下载了上千张图片。
请看代码:
# 导包
import requests
from time import sleep
import os
import threading
import parsel
import random

if not os.path.exists('image'):
    os.mkdir('image')

# base_url = 'https://anime-pictures.net/pictures/view_posts/0?lang=en'

headers = {
    'User-Agent':
        'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36'
}


def get(url, headers):
    '''请求数据'''
    response = requests.get(url, headers)
    html_data = response.text
    return html_data


def parsel_data(html_data):
    '''筛选数据'''
    selector = parsel.Selector(html_data)
    result_list = selector.xpath('//span[@class="img_block_big"]')

    for result in result_list:
        image_url = result.xpath('./a/picture/source/img/@src').extract_first()
        image_id = result.xpath('./a/picture/source/img/@id').extract_first()

        img_url = 'https:' + image_url  # 手动拼url

        all_title = img_url
        img_name = image_id + '.' + img_url.split('.')[-1]

        img_data = requests.get(url=all_title, headers=headers).content

        yield all_title, image_id, img_data, img_name


def save(all_title, image_id, img_data,img_name):
    '''保存数据'''
    try:
        with open('image\\' + str(random.randint(0,1000000)) + os.path.splitext(img_name)[1], mode='wb') as f:
            print('保存成功:', image_id)
            f.write(img_data)
    except:
        print('保存失败:', image_id, '(|・ω・` ))')


def start_save(base_url):
    html_data = get(url=base_url, headers=headers)
    for image_data in parsel_data(html_data):
        all_title = image_data[0]  # url https://xxxxxxxxxx...
        img_id = image_data[1]  # ID
        img_data = image_data[2]  # 数据
        img_name = image_data[3] #文件名
        save(all_title=all_title, image_id=img_id, img_data=img_data,img_name = img_name)            

def main(page):
    for page in range(0, page + 1):
        print('###############正在下载第{}页数据###############'.format(page))
        base_url = 'https://anime-pictures.net/pictures/view_posts/0?lang=en'.format(page)
        if page>0:
            print('休息哈|ू・ω・` )')
            sleep(2)

        my_thread = threading.Thread(target=start_save, args=(base_url,)) #启动多线程
        my_thread.setDaemon(True)
        my_thread.start()

        

if __name__ == '__main__':
    lock = threading.RLock()
    main(6300)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-1-19 20:27

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表