2012-05-08 4 views
0

여러 링크를 동시에 다운로드하려면 어떻게해야합니까? 아래 스크립트는 작동하지만 한 번에 하나만 다운로드하면 속도가 매우 느립니다. 스크립트에서 멀티 스레딩을 통합하는 방법을 알 수 없습니다.빠른 다운로드를위한 멀티 스레딩

파이썬 스크립트 : HTML 파일이 links.html라고

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) 

가 : - 생산자의 문제 -

<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> 
+3

: 추가 정보를 위해

. – kindall

+0

open (full_path, 'wb'). 쓰기 (변환 됨) !!! – User

답변

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 
+0

이 오류가 발생했습니다. NameError : name 'queue'가 정의되지 않았습니다. ''Queue "를 대문자로 사용하면이 오류가 발생합니다. AttributeError : 'module'객체에는 'put'' 속성이 없습니다. – Blainer

+1

같은 이름의 모듈을 가져 왔을 때 정말로'thread'라는 함수를 갖고 싶습니까? – mgilson

+0

오른쪽. 이것은 멀티 스레딩을 알고 있기 때문에 구조의 제안 일뿐 해결책이 아닙니다. – User

7

내가 일을 병렬화에 대한 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

나는이 오류를 받고있다. AssertionError : 163319020에서의 잘못된 요소 프록시' – Blainer

+0

@Blainer : 좀 이상하다. (lxml.html이 어떻게 작동하는지 모르겠지만 어쩌면 isn하지 않을 수도있다. '티...). 링크 대신 URL을 전달할 수 있습니다. 어떤 정보 lxml.html은'multiprocessing'에 의해 pickle/unpickle되지 않는 파일의 위치에 어떤 종류의 프록시/핸들을 유지할 수 있습니다. 만약 link.get이 문자열을 반환한다면, 그것은 조금 더 멋지게 재생해야합니다 ... – mgilson

+1

나는 남자를 모른다, 이것은 하하 – Blainer

1

2017 년 asyncio하고있는 ThreadPoolExecutor 같은 지금 몇 가지 다른 옵션이 있습니다. 여기

는 (파이썬 미래에 포함됨)에 ThreadPoolExecutor 예

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()) 

제출() 함수는 큐에 작업을 제출할 것이다.

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 코어의 수는 몇 가지 테스트는 FAW 당신이 컨텍스트 스위칭 오버 헤드에 따라 최대 갈 수있는 방법을 보려면 않습니다. 실제로 우리가 도움을 줄 수있는 문제가 발생하지 않도록 당신도, 아직 아무것도 시도하지 않은 https://docs.python.org/3/library/concurrent.futures.html