2016-07-29 4 views
2

나는 쓰레드 된 스크립트에서 첫 시도를하고있다. 결국 이전에 만든 원래의 선형 스크래핑 스크립트보다 조금 더 빠르게 작동하는 웹 스크래퍼가 될 것입니다.Python Threading/Thread Implement

몇 시간 동안 읽고 예제 코드로 재생 한 후. 여전히 구현이 간다면 무엇이 옳은지 확실하지 않습니다.

from Queue import Queue 
import threading 

def scrape(queue): 
    global workers 
    print worker.getName() 
    print queue.get() 
    queue.task_done() 
    workers -= 1 

queue = Queue(maxsize=0) 
threads = 10 
workers = 0 


with open('test.txt') as in_file:  
    for line in in_file: 
     queue.put(line) 

while not (queue.empty()): 
    if (threads != workers): 
     worker = threading.Thread(target=scrape, args=(queue,)) 
     worker.setDaemon(True) 
     worker.start() 
     workers += 1 

아이디어는 내가있는 test.txt 파일의 URL 목록을 가지고있다 :

현재 내가 가지고 노는 한 다음과 같은 코드가 있습니다. 파일을 열고 모든 URL을 대기열에 넣습니다. 거기에서 나는 큐에서 당겨서 10 개의 쓰레드를 실행하고 웹 페이지를 긁어 낸다. 또는이 예제에서는 잡아 당긴 라인을 단순히 출력한다.

일단 작업이 완료되면 '작업자 스레드'가 제거 된 다음 대기열이 비어있을 때까지 새 작업자 스레드가 교체됩니다.

내 실제 구현에서 어느 시점에서 필자는 내 함수 스크랩에서 데이터를 가져 와서 .csv 파일에 써야 할 것입니다. 하지만, 지금 당장은 스레드를 올바르게 구현하는 방법을 이해하려고 시도하고 있습니다.

나는 'Thread'를 사용하는 비슷한 예제를 보았습니다 ... 또한 상속 된 클래스를 활용하는 'threading'예제를 보았습니다. 나는 내가 무엇을 사용해야하며 그것을 관리하는 적절한 방법을 알고 싶다.

나를 쉽게 편하게 여기십시오. 실은 초보자가 실을 이해하려고 애 쓰고 .... 그렇습니다. 매우 복잡 할 수 있습니다. 그러나 이것은 처음 시도하기에 충분히 쉬워야한다고 생각합니다 ...

+0

일반적으로 스레딩은 상당히 복잡하며 대부분의 경우 다중 처리 (.dummy) 또는 동시 처리와 같은 추상화 라이브러리를 사용하는 것이 더 쉽습니다. – janbrohl

답변

2

On Python 2.x multiprocessing.dummy (스레드 사용)은 사용하기 쉽기 때문에 좋은 선택입니다 (Python 3.x에서도 가능함)

스크래핑이 CPU로 제한되어 있고 CPU 코어가 여러 개인 경우이 방법을 사용하면 실제로는 multiprocessing으로 전환하여 큰 속도 향상을 얻을 수 있습니다.

(파이썬은 종종 때문에 performance optimization의 여러 프로세스와만큼 스레딩과 여러 CPU에서 이익을하지 않습니다 - 당신은 귀하의 경우 빠른 무엇인지 자신을 찾을 수있다) 당신이 할 수 mutliprocessing.dummy와

을 파이썬 3.x를에

from multiprocessing.dummy import Pool 
# from multiprocessing import Pool # if you want to use more cpus 

def scrape(url): 
    data = {"sorted": sorted(url)} # normally you would do something more interesting 
    return (url, data) 

urls=[] 
threads = 10 

if __name__=="__main__": 
    with open('test.txt') as in_file:  
     urls.extend(in_file) # lines 

    p=Pool(threads) 
    results=list(p.imap_unordered(scrape,urls)) 
    p.close() 
    print results # normally you would process your results here 

, concurrent.futures는 더 나은 선택이 될 수 있습니다.

+0

처음 보면 훨씬 쉬워 보입니다. 또한, 조금 놀아 본 후에는 더 빠릅니다. 스크립트의 실제 스크래핑 부분에서 실행중인 한 가지 문제점은 .csv에 쓰려고하는 스크래핑 된 정보처럼 공유하고 싶지 않은 변수를 공유한다는 것입니다. 스크래핑을 시작하기 위해 5 개의 스레드를 실행하면 스크래퍼가 원하는 페이지를 제대로 방문 했음에도 불구하고 내 CSV에 5 개의 복제본이 작성됩니다. 내 스레드를 Lock() 및 Release() 할 때 스크립트는 다시 선형 적으로 실행됩니다. 스레드가 서로 다른 데이터를 쓰지 못하게하려면 어떻게해야합니까? –

+0

나중에 쓰려고하는 쓰레드/프로세스간에 정보를 공유하고 싶지 않다면 스크랩 함수의 반환 값에 넣으십시오 - 함수 외부의 변수에 쓰지 마십시오. – janbrohl

+0

해야합니다. 예제 코드에서 스레드와 다중 처리에 대해 많은 것을 배웠다. 그냥 고마워. 또한 IMO를 구현하기 위해 멀티 프로세싱이 훨씬 빨라졌으며 더 깨끗했습니다. 이것이 전문 개발자가 선택한 모듈인지 궁금하십니까? 아니면 낮은 수준의 스레드 모듈에 이점이 있습니까? –