首先,我是Python的新手。这与问题无关,但我必须提及它。
我正在创建一个爬虫作为我的第一个项目,以了解Python中的工作原理,但到目前为止这是我的主要问题...在使用requests
时理解终端中的“如何获取多个进度条”和pathos.multiprocessing
。
我设法完成了一切,我只想拥有更漂亮的输出,所以我决定添加进度条。我正在使用tqdm
,因为我喜欢它,看起来最容易实现。
这是我的方法,目的是下载文件。
def download_lesson(self, lesson_data):
if not 'file' in lesson_data:
return print('=> Skipping... File {file_name} already exists.'.format(file_name=lesson_data['title']))
response = requests.get(lesson_data['video_source'], stream=True)
chunk_size = 1024
with open(lesson_data['file'], 'wb') as file:
progress = tqdm(
total=int(response.headers['Content-Length']),
unit='B',
unit_scale=True
)
for chunk in response.iter_content(chunk_size=chunk_size):
if chunk:
progress.update(len(chunk))
file.write(chunk)
progress.close()
print('=> Success... File "{file_name}" has been downloaded.'.format(file_name=lesson_data['title']))
我通过Processing
:
# c = instance of my crawling class
# cs = returns the `lesson_data` for `download_lesson` method
p = Pool(1)
p.map(c.download_lesson, cs)
所以一切都很有效,因为我在processes=1
中使用Pool
。但是,当我运行多个进程时,让我们说processes=3
然后事情开始变得奇怪,我在另一个内部得到了多个进程。
我在tqdm documentation中发现position
有参数。这清楚地说明了在这种情况下我需要的目的。
position:int,optional 指定行偏移以打印此栏(从0开始)如果未指定则自动。用于一次管理多个条(例如,从线程)。
但是,我没有提供如何设置该位置的线索。我尝试了一些奇怪的东西,比如添加一个被自己递增的变量,但是每当运行方法download_lesson
时,它似乎没有做任何递增。始终0
所以位置始终为0
。
在这种情况下似乎我不太了解...欢迎任何提示,提示或完整的解决方案。谢谢!
更新#1:
我发现我也可以将另一个参数传递给地图,所以我传递了大量正在设置的进程。 (例如,进程= 2)
p = Pool(config['threads'])
p.map(c.download_lesson, cs, range(config['threads']))
所以,在我的方法中,我试图打印出那个参数,确实我得到0
和1
,因为我在示例中运行2
个进程。
但这似乎根本没有做任何事......
progress = tqdm(
total=int(response.headers['Content-Length']),
unit='B',
unit_scale=True,
position=progress_position
)
我仍然遇到重叠进度条的问题。当我手动将位置设置为(例如10)时,它会在终端跳转,因此位置会移动,仍然会重叠,因为现在两者都设置为10.但是当动态设置时,它似乎也不起作用。我不明白这里的问题是什么......就像地图运行这个方法两次一样,它仍然给出了两个进度条的最新设置位置。我到底做错了什么?
答案 0 :(得分:0)
好的,首先我要感谢@MikeMcKerns的评论...... 所以我的脚本有很多变化,因为我想要不同的方法,但最终归结为这些重要的变化。
我的init.py
现在看起来更干净了......
from scraper.Crawl import Crawl
if __name__ == '__main__':
Crawl()
我scraper.Crawl
类中的download_lesson
类的方法现在看起来像这样......
def download_lesson(self, lesson):
response = requests.get(lesson['link'], stream=True)
chunk_size = 1024
progress = tqdm(
total=int(response.headers['Content-Length']),
unit='B',
unit_scale=True
)
with open(lesson['file'], 'wb') as file:
for chunk in response.iter_content(chunk_size=chunk_size):
progress.update(len(chunk))
file.write(chunk)
progress.close()
最后,我有一个专门用于多处理的方法,如下所示:
def begin_processing(self):
pool = ThreadPool(nodes=Helper.config('threads'))
for course in self.course_data:
pool.map(self.download_lesson, course['lessons'])
print(
'Course "{course_title}" has been downloaded, with total of {lessons_amount} lessons.'.format(
course_title=course['title'],
lessons_amount=len(course['lessons'])
)
)
你可以说,我对我的班级进行了一些重大改动,但最重要的是我必须将这一点添加到我的init.py
if __name__ == '__main__':
其次,我不得不使用@MikeMcKerns建议我看看的内容:
from pathos.threading import ThreadPool
因此,随着这些变化,我终于在我需要的时候完成了所有工作。这是一个快速截图。
即使如此,我仍然没有任何线索,为什么pathos.multiprocessing
使tqdm
进展非常错误,我设法解决了我的问题,感谢Mike的建议。谢谢!