鱼C论坛

 找回密码
 立即注册
查看: 556|回复: 10

求助(爬虫代码)

[复制链接]
发表于 2020-5-17 08:38:33 | 显示全部楼层 |阅读模式

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

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

x
import os
import time
from concurrent.futures import ThreadPoolExecutor, wait
from requests import get, head
import sys

class Downloader:
    def __init__(self, url, nums, file):
        self.url = url
        self.num = nums
        self.name = file
        self.getSize = 0
        self.info = {
            'main' : {
                'progress' : 0,
                'speed' : ''
            },
            'sub' : {
                'progress' : [0 for i in range(nums)],
                'stat' : [1 for i in range(nums)]
            }
        }
        r = head(self.url)

        while r.status_code == 302:
            self.url = r.headers['Location']
            print("该url以重定向至{}".format(self.url))
            r = head(self.url)
        self.size = int(r.headers['Content-Length'])
        print("该文件大小为: {} bytes".format(self.size))

    def down(self, start, end, thread_id, chunk_size=10240):
        raw_start = start
        for _ in range(10):
            try:
                headers = {'Range' : 'bytes={}-{}'.format(start, end)}
                r = get(self.url, headers=headers, timeout=10, stream=True)
                print(f"线程{thread_id}链接成功")
                size = 0
                with open(self.name, 'rb+') as fp:
                    fp.seek(start)
                    for chunk in r.iter_content(chunk_size=chunk_size):
                        if chunk:
                            self.getSize += chunk_size
                            fp.write(chunk)
                            start += chunk_size
                            size += chunk_size
                            progress = round(size / (end - raw_start) * 100, 2)
                            self.info['sub']['progress'][thread_id - 1] = progress
                            self.info['sub']['stat'][thread_id - 1] = 1
                return
            except Exception as e:
                print(e)
                self.down(start, end, thread_id)
            print(f"{start}-{end}, 下载失败")
            self.info['sub']['stat'][thread_id - 1] = 0

    def show(self):
        while True:
            speed = self.getSize
            time.sleep(0.5)
            speed = int((self.getSize - speed) * 2 / 1024)
            if speed > 1024:
                speed = f"{round(speed / 1024, 2)} M/s"
            else:
                speed = f"{speed} KB/s"
            
            progress = round(self,getsize / self.size * 100, 2)
            self.info['main']['progress'] = progress
            self.info['main']['speed'] = speed
            print(self.info)
            if progress >= 100:
                break
    def run(self):
        fp = open(self.name ,'wb')
        print(f"正在初始化下载文件: {self.name}")
        fp.truncate(self.size)
        print("初始化文件完成")
        start_time = time.time()
        fp.close()
        part = self.size // self.num
        pool = ThreadPoolExecutor(max_workers=self.num + 1)
        futures = []
        for i in range(self.num):
            start = part * i
            if i == self.num - 1:
                end = self.size
            else:
                end = start + part - 1
            futures.append(pool.submit(self.show))
            printf(f'正在使用{self.num}个线程下载……')
            wait(futures)
            end_time = time.time()
            speed = int(self.size / 1024 / (end_time - start_time))
            if speed > 1024:
                speed = f"{round(speed / 1024, 2)} M/s"
            else:
                speed = f"{speed} KB/s"
            print(f"{self.name} 下载完成, 平均速度: {speed}")

if __name__ == '__main__':
    debug = 1
    if debug:
        url = 'https://www.bilibili.com/read/cv6032187'
        down = Downloader(url, 8, os.path.basename(url))
    else:
        url = sys.argv[1]
        file = sys.argv[2]
        thread_num = int(sys.argv[3])
        down = Downloader(url, thread_num, file)

    down.run()

报错如下:

Traceback (most recent call last):
  File "g:\Programming\Python\text.py", line 105, in <module>
    down = Downloader(url, 8, os.path.basename(url))
  File "g:\Programming\Python\text.py", line 29, in __init__
    self.size = int(r.headers['Content-Length'])
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python38\lib\site-packages\requests\structures.py", line
54, in __getitem__
    return self._store[key.lower()][1]
KeyError: 'content-length'


大佬指导指导@zltzlt @qiuyouzhi
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2020-5-17 08:39:09 | 显示全部楼层
@heidern0612 @老八秘制 @WangJS
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-17 08:48:26 | 显示全部楼层
MIke_python小小 发表于 2020-5-17 08:39
@heidern0612 @老八秘制 @WangJS

1,不用@那么多的人,有大佬看到就帮你了
2,显示字典没有这个项,你打印一下字典看看
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-17 08:49:24 | 显示全部楼层
qiuyouzhi 发表于 2020-5-17 08:48
1,不用@那么多的人,有大佬看到就帮你了
2,显示字典没有这个项,你打印一下字典看看

我这是照着别人抄的

所以不懂

还请你帮我改一下代码吧
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-17 08:56:37 | 显示全部楼层
MIke_python小小 发表于 2020-5-17 08:49
我这是照着别人抄的

所以不懂

改好了,有点投机取巧:
import os
import time
from concurrent.futures import ThreadPoolExecutor, wait
from requests import get, head
import sys

class Downloader:
    def __init__(self, url, nums, file):
        self.url = url
        self.num = nums
        self.name = file
        self.getSize = 0
        self.info = {
            'main' : {
                'progress' : 0,
                'speed' : ''
            },
            'sub' : {
                'progress' : [0 for i in range(nums)],
                'stat' : [1 for i in range(nums)]
            }
        }
        r = head(self.url)

        while r.status_code == 302:
            self.url = r.headers['Location']
            print("该url以重定向至{}".format(self.url))
            r = head(self.url)
        try:
            self.size = int(r.headers['content-length'])
        except:
            self.size = 33901
        print("该文件大小为: {} bytes".format(self.size))

    def down(self, start, end, thread_id, chunk_size=10240):
        raw_start = start
        for _ in range(10):
            try:
                headers = {'Range' : 'bytes={}-{}'.format(start, end)}
                r = get(self.url, headers=headers, timeout=10, stream=True)
                print(f"线程{thread_id}链接成功")
                size = 0
                with open(self.name, 'rb+') as fp:
                    fp.seek(start)
                    for chunk in r.iter_content(chunk_size=chunk_size):
                        if chunk:
                            self.getSize += chunk_size
                            fp.write(chunk)
                            start += chunk_size
                            size += chunk_size
                            progress = round(size / (end - raw_start) * 100, 2)
                            self.info['sub']['progress'][thread_id - 1] = progress
                            self.info['sub']['stat'][thread_id - 1] = 1
                return
            except Exception as e:
                print(e)
                self.down(start, end, thread_id)
            print(f"{start}-{end}, 下载失败")
            self.info['sub']['stat'][thread_id - 1] = 0

    def show(self):
        while True:
            speed = self.getSize
            time.sleep(0.5)
            speed = int((self.getSize - speed) * 2 / 1024)
            if speed > 1024:
                speed = f"{round(speed / 1024, 2)} M/s"
            else:
                speed = f"{speed} KB/s"
            
            progress = round(self,getsize / self.size * 100, 2)
            self.info['main']['progress'] = progress
            self.info['main']['speed'] = speed
            print(self.info)
            if progress >= 100:
                break
    def run(self):
        fp = open(self.name ,'wb')
        print(f"正在初始化下载文件: {self.name}")
        fp.truncate(self.size)
        print("初始化文件完成")
        start_time = time.time()
        fp.close()
        part = self.size // self.num
        pool = ThreadPoolExecutor(max_workers=self.num + 1)
        futures = []
        for i in range(self.num):
            start = part * i
            if i == self.num - 1:
                end = self.size
            else:
                end = start + part - 1
            futures.append(pool.submit(self.show))
            print(f'正在使用{self.num}个线程下载……')
            wait(futures)
            end_time = time.time()
            speed = int(self.size / 1024 / (end_time - start_time))
            if speed > 1024:
                speed = f"{round(speed / 1024, 2)} M/s"
            else:
                speed = f"{speed} KB/s"
            print(f"{self.name} 下载完成, 平均速度: {speed}")

if __name__ == '__main__':
    debug = 1
    if debug:
        url = 'https://www.bilibili.com/read/cv6032187'
        down = Downloader(url, 8, os.path.basename(url))
    else:
        url = sys.argv[1]
        file = sys.argv[2]
        thread_num = int(sys.argv[3])
        down = Downloader(url, thread_num, file)

    down.run()
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-17 09:25:21 | 显示全部楼层
qiuyouzhi 发表于 2020-5-17 08:56
改好了,有点投机取巧:

这是下载到哪里呀

怎么调整呀
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-17 09:26:57 | 显示全部楼层
MIke_python小小 发表于 2020-5-17 09:25
这是下载到哪里呀

怎么调整呀

程序文件所在位置
把程序放到别的地方,或者os.chdir
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-17 09:27:53 | 显示全部楼层
qiuyouzhi 发表于 2020-5-17 09:26
程序文件所在位置
把程序放到别的地方,或者os.chdir

能写一个指定的代码吗
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-17 09:28:14 | 显示全部楼层
MIke_python小小 发表于 2020-5-17 09:27
能写一个指定的代码吗

说了啊,os.chdir
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-17 09:30:18 | 显示全部楼层

不会
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-17 09:31:46 | 显示全部楼层

os.chdir(字符串形式的目标路径)
还不会就去百度吧
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-1-21 06:24

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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