我想下载20个csv文件,其大小全部在一起 - 5MB
这是我的代码的第一个版本:
import os
from bs4 import BeautifulSoup
import urllib.request
import datetime
def get_page(url):
try:
return urllib.request.urlopen(url).read()
except:
print("[warn] %s" % (url))
raise
def get_all_links(page):
soup = BeautifulSoup(page)
links = []
for link in soup.find_all('a'):
url = link.get('href')
if '.csv' in url:
return url
print("[warn] Can't find a link with CSV file!")
def get_csv_file(company):
link = 'http://finance.yahoo.com/q/hp?s=AAPL+Historical+Prices'
g = link.find('s=')
name = link[g + 2:g + 6]
link = link.replace(name, company)
urllib.request.urlretrieve(get_all_links(get_page(link)), os.path.join('prices', company + '.csv'))
print("[info][" + company + "] Download is complete!")
if __name__ == "__main__":
start = datetime.datetime.now()
security_list = ["AAPL", "ADBE", "AMD", "AMZN", "CRM", "EXPE", "FB", "GOOG", "GRPN", "INTC", "LNKD", "MCD", "MSFT", "NFLX", "NVDA", "NVTL", "ORCL", "SBUX", "STX"]
for security in security_list:
get_csv_file(security)
end = datetime.datetime.now()
print('[success] Total time: ' + str(end-start))
此代码会在1.2分钟内将所有大小相同的20个csv文件下载到5MB
。
然后我尝试使用multiprocessing
使其下载速度更快
这是版本2:
if __name__ == "__main__":
import multiprocessing
start = datetime.datetime.now()
security_list = ["AAPL", "ADBE", "AMD", "AMZN", "CRM", "EXPE", "FB", "GOOG", "GRPN", "INTC", "LNKD", "MCD", "MSFT", "NFLX", "NVDA", "NVTL", "ORCL", "SBUX", "STX"]
for i in range(20):
p = multiprocessing.Process(target=hP.get_csv_files([index] + security_list), args=(i,))
p.start()
end = datetime.datetime.now()
print('[success] Total time: ' + str(end-start))
但是,不幸的是,版本2会在2.4分钟内将20个csv文件的大小全部下载到5MB
。
为什么multiprocessing
会减慢我的计划?
我做错了什么?
比现在更快下载这些文件的最佳方法是什么?
谢谢?
答案 0 :(得分:4)
我不知道你试图从你的例子中开始使用Process(我认为你有一些错别字)。我想你想要这样的东西:
processs = []
for security in security_list:
p = multiprocessing.Process(target=get_csv_file, args=(security,))
p.start()
processs.append(p)
for p in processs:
p.join()
您可以通过这种方式在安全性上进行迭代,为每个安全名称创建一个新进程,并将该进程放在一个列表中。
启动所有进程后,循环遍历它们并等待它们完成,使用join。
使用Pool及其并行映射实现还有一种更简单的方法。
pool = multiprocessing.Pool(processes=5)
pool.map(get_csv_file, security_list)
您创建了一个进程池(如果省略该参数,它将创建一个等于您的处理器数的数字),然后使用map将您的函数应用于列表中的每个元素。游泳池将负责其余的工作。