2009-12-24 6 views
3

내가 아니라 디스크 파일을pycurl로 많은 페이지를 가져 옵니까?

curl "http://farmsubsidy.org/DE/browse?page=[0000-3603]" -o "de.#1" 

같은 웹 사이트에서 많은 페이지를 얻을 수 있지만, 파이썬에서 페이지의 데이터를 얻을 싶어요. 사람은
또는 고속 urllib2 (한번에 하나씩되지 않음)이 가능하다면,
또는 다른 말은 "그것을 잊지, 컬이 더 빠르고 더 강력"이 작업을 수행하는 pycurl 코드를 게시하시기 바랍니다 수 있습니까? 감사합니다

답변

3

여기 urllib2 및 스레드를 기반으로 한 솔루션입니다.

import urllib2 
from threading import Thread 

BASE_URL = 'http://farmsubsidy.org/DE/browse?page=' 
NUM_RANGE = range(0000, 3603) 
THREADS = 2 

def main(): 
    for nums in split_seq(NUM_RANGE, THREADS): 
     t = Spider(BASE_URL, nums) 
     t.start() 

def split_seq(seq, num_pieces): 
    start = 0 
    for i in xrange(num_pieces): 
     stop = start + len(seq[i::num_pieces]) 
     yield seq[start:stop] 
     start = stop 

class Spider(Thread): 
    def __init__(self, base_url, nums): 
     Thread.__init__(self) 
     self.base_url = base_url 
     self.nums = nums 
    def run(self): 
     for num in self.nums: 
      url = '%s%s' % (self.base_url, num) 
      data = urllib2.urlopen(url).read() 
      print data 

if __name__ == '__main__': 
    main() 
+0

'class Spider' - 아주 멋지다! –

+0

감사합니다. Corey; 어떻게해야합니까 (초보자에게) 모두 완료 될 때까지 기다려야합니까? – denis

+0

Denis, main()의 각 스레드에서 join()을 호출 할 수 있습니다. 스레드가 완료 될 때까지 차단됩니다. –

1

그냥 for 루프 안에 bash 스크립트에 넣을 수 있습니다.

그러나 파이썬을 사용하여 각 페이지를 구문 분석 할 때 더 성공적 일 수 있습니다. http://www.securitytube.net/Crawling-the-Web-for-Fun-and-Profit-video.aspx 정확한 데이터를 얻고 동시에 db에 저장할 수 있습니다. http://www.securitytube.net/Storing-Mined-Data-from-the-Web-for-Fun-and-Profit-video.aspx

+0

curl은 전체 전송 중에 지속적 연결을 유지하므로 3600 TCP의 새로운 연결을위한 쉘 루프를 수행하면 훨씬 느려집니다 ... –

+0

계속해서 연속적으로 실행됩니다. 병렬로 많은 스트림을 다운로드 할 수있는 버전에 대한 내 대답을 참조하십시오. –

+0

예, 그리고 꽤 가능성이 여러 스레드에서 pycurl을 사용하여 더 빨리 될 것입니다! ;-) –

6

따라서 두 가지 문제가 있으며 한 가지 예를 들어 설명하겠습니다. pycurl이 이미 멀티 스레딩을 수행했거나 한 번에 한 번에 열심히하지 않았 음을 주목하십시오.

#! /usr/bin/env python 

import sys, select, time 
import pycurl,StringIO 

c1 = pycurl.Curl() 
c2 = pycurl.Curl() 
c3 = pycurl.Curl() 
c1.setopt(c1.URL, "http://www.python.org") 
c2.setopt(c2.URL, "http://curl.haxx.se") 
c3.setopt(c3.URL, "http://slashdot.org") 
s1 = StringIO.StringIO() 
s2 = StringIO.StringIO() 
s3 = StringIO.StringIO() 
c1.setopt(c1.WRITEFUNCTION, s1.write) 
c2.setopt(c2.WRITEFUNCTION, s2.write) 
c3.setopt(c3.WRITEFUNCTION, s3.write) 

m = pycurl.CurlMulti() 
m.add_handle(c1) 
m.add_handle(c2) 
m.add_handle(c3) 

# Number of seconds to wait for a timeout to happen 
SELECT_TIMEOUT = 1.0 

# Stir the state machine into action 
while 1: 
    ret, num_handles = m.perform() 
    if ret != pycurl.E_CALL_MULTI_PERFORM: 
     break 

# Keep going until all the connections have terminated 
while num_handles: 
    # The select method uses fdset internally to determine which file descriptors 
    # to check. 
    m.select(SELECT_TIMEOUT) 
    while 1: 
     ret, num_handles = m.perform() 
     if ret != pycurl.E_CALL_MULTI_PERFORM: 
      break 

# Cleanup 
m.remove_handle(c3) 
m.remove_handle(c2) 
m.remove_handle(c1) 
m.close() 
c1.close() 
c2.close() 
c3.close() 
print "http://www.python.org is ",s1.getvalue() 
print "http://curl.haxx.se is ",s2.getvalue() 
print "http://slashdot.org is ",s3.getvalue() 

마지막으로,이 코드는 주로 pycurl 사이트에 대한 예제를 기반으로 =. =

당신이 정말로 문서를 읽어야 할 수있다. ppl은 그것에 막대한 시간을 소비합니다.

+2

파이썬 수준에서 멀티 쓰레드 접근법을 사용하려고하면 파이썬 길 문제로 인해 실제로는 병렬 페이지를 가져 오지 못합니다. C에 의해 작성된 curl lib에 감사드립니다. curl lib에 의한 multi_perfrom은 진정으로 멀티 스레딩입니다. 이것이 제가 생각할 수있는 가장 빠른 접근법입니다. – user425996

+0

다음은 CurlMulti의 좋은 예입니다. http://fragmentsofcode.wordpress.com/2011/01/22/pycurl-curlmulti-example/ – Javier

1

을 scrapy하는 모습을 가져야한다 -

잡아 헤드 페이지 :

page = Soup(requests.get(url='http://rootpage.htm').text) 

가의 배열을 만들기 요청 :

from requests import async 

requests = [async.get(url.get('href')) for url in page('a')] 
responses = async.map(requests) 

[dosomething(response.text) for response in responses] 

요청시이 작업을 수행하려면 gevent가 필요합니다.

1

나는 human_curl

봐 예제의 사용자 비동기 모듈을 추천 할 수 있습니다 :

from urlparse import urljoin 
from datetime import datetime 

from human_curl.async import AsyncClient 
from human_curl.utils import stdout_debug 

def success_callback(response, **kwargs): 
    """This function call when response successed 
    """ 
    print("success callback") 
    print(response, response.request) 
    print(response.headers) 
    print(response.content) 
    print(kwargs) 

def fail_callback(request, opener, **kwargs): 
    """Collect errors 
    """ 
    print("fail callback") 
    print(request, opener) 
    print(kwargs) 

with AsyncClient(success_callback=success_callback, 
       fail_callback=fail_callback) as async_client: 
    for x in xrange(10000): 
     async_client.get('http://google.com/', params=(("x", str(x)),) 
     async_client.get('http://google.com/', params=(("x", str(x)),), 
         success_callback=success_callback, fail_callback=fail_callback) 

사용이 매우 간단합니다. 그런 다음 실패한 async_client가로드 된 페이지 성공이 콜백으로 호출됩니다. 또한 병렬 연결에서 번호를 지정할 수 있습니다.