如何同时下载多个链接?我下面的脚本有效,但一次只下载一个,速度非常慢。我无法弄清楚如何在我的脚本中加入多线程。
Python脚本:
from BeautifulSoup import BeautifulSoup
import lxml.html as html
import urlparse
import os, sys
import urllib2
import re
print ("downloading and parsing Bibles...")
root = html.parse(open('links.html'))
for link in root.findall('//a'):
url = link.get('href')
name = urlparse.urlparse(url).path.split('/')[-1]
dirname = urlparse.urlparse(url).path.split('.')[-1]
f = urllib2.urlopen(url)
s = f.read()
if (os.path.isdir(dirname) == 0):
os.mkdir(dirname)
soup = BeautifulSoup(s)
articleTag = soup.html.body.article
converted = str(articleTag)
full_path = os.path.join(dirname, name)
open(full_path, 'w').write(converted)
print(name)
名为links.html
的HTML文件:
<a href="http://www.youversion.com/bible/gen.1.nmv-fas">http://www.youversion.com/bible/gen.1.nmv-fas</a>
<a href="http://www.youversion.com/bible/gen.2.nmv-fas">http://www.youversion.com/bible/gen.2.nmv-fas</a>
<a href="http://www.youversion.com/bible/gen.3.nmv-fas">http://www.youversion.com/bible/gen.3.nmv-fas</a>
<a href="http://www.youversion.com/bible/gen.4.nmv-fas">http://www.youversion.com/bible/gen.4.nmv-fas</a>
答案 0 :(得分:8)
我使用multiprocessing
来并行化事物 - 出于某种原因,我比threading
from BeautifulSoup import BeautifulSoup
import lxml.html as html
import urlparse
import os, sys
import urllib2
import re
import multiprocessing
print ("downloading and parsing Bibles...")
def download_stuff(link):
url = link.get('href')
name = urlparse.urlparse(url).path.split('/')[-1]
dirname = urlparse.urlparse(url).path.split('.')[-1]
f = urllib2.urlopen(url)
s = f.read()
if (os.path.isdir(dirname) == 0):
os.mkdir(dirname)
soup = BeautifulSoup(s)
articleTag = soup.html.body.article
converted = str(articleTag)
full_path = os.path.join(dirname, name)
open(full_path, 'w').write(converted)
print(name)
root = html.parse(open('links.html'))
links = root.findall('//a')
pool = multiprocessing.Pool(processes=5) #use 5 processes to download the data
output = pool.map(download_stuff,links) #output is a list of [None,None,...] since download_stuff doesn't return anything
答案 1 :(得分:2)
2017年还有其他一些选择,比如asyncio和ThreadPoolExecutor。
以下是ThreadPoolExecutor(包含在Python期货中)
的示例from concurrent.futures import ThreadPoolExecutor
def download(url, filename):
... your dowload function...
pass
with ThreadPoolExecutor(max_workers=12) as executor:
future = executor.submit(download, url, filename)
print(future.result())
submit()函数会将任务提交到队列中。 (为您完成队列管理)
Python version 3.5 and above:
if max_workers is None or not given, it will default to the number of processors on the
machine, multiplied by 5.
你可以设置max_workers,实际上是CPU内核数量的几倍,做一些测试,看看你可以上升到多少,取决于上下文切换开销。
欲了解更多信息: https://docs.python.org/3/library/concurrent.futures.html
答案 2 :(得分:1)
在我看来,消费者 - 生产者问题 - 请参阅维基百科
您可以使用
import Queue, thread
# create a Queue.Queue here
queue = Queue.Queue()
print ("downloading and parsing Bibles...")
root = html.parse(open('links.html'))
for link in root.findall('//a'):
url = link.get('href')
queue.put(url) # produce
def thrad():
url = queue.get() # consume
name = urlparse.urlparse(url).path.split('/')[-1]
dirname = urlparse.urlparse(url).path.split('.')[-1]
f = urllib2.urlopen(url)
s = f.read()
if (os.path.isdir(dirname) == 0):
os.mkdir(dirname)
soup = BeautifulSoup(s)
articleTag = soup.html.body.article
converted = str(articleTag)
full_path = os.path.join(dirname, name)
open(full_path, 'wb').write(converted)
print(name)
thread.start_new(thrad, ()) # start 1 threads