>  기사  >  백엔드 개발  >  Python을 사용하여 크롤러를 만드는 방법

Python을 사용하여 크롤러를 만드는 방법

高洛峰
高洛峰원래의
2016-11-23 13:23:371196검색

"시작하기"는 좋은 동기 부여가 되지만 작업 속도가 느릴 수 있습니다. 프로젝트가 손에 있거나 마음에 있다면 실제로는 목표 지향적이며 학습처럼 천천히 배우지 않을 것입니다.

또한 지식 시스템의 각 지식 포인트가 그래프의 포인트이고 종속 관계가 에지인 경우 A 학습 경험 때문에 이 그래프는 방향성 비순환 그래프가 되어서는 안 됩니다. B를 배우는 데 도움이 될 수 있습니다. 따라서 "시작"하는 방법을 배울 필요가 없습니다. 왜냐하면 그러한 "시작" 지점이 존재하지 않기 때문입니다. 당신이 배워야 할 것은 그 과정에서 어떻게 해야 하는가입니다! 물론, 파이썬을 먼저 알아야 한다고 주장할 수도 있고, 그렇지 않으면 크롤러를 만들기 위해 파이썬을 어떻게 배울 수 있습니까? 그러나 실제로 이것을 만드는 과정에서 파이썬을 배울 수 있습니까? 크롤러 :D

위의 많은 답변을 참조하세요. 그들은 모두 "기술"(사용할 소프트웨어 및 크롤링 방법)에 대해 이야기합니다. 따라서 "Tao" 및 "기술"(크롤러 작동 방식 및 방법)에 대해 이야기하겠습니다. Python으로 구현하려면

간단히 요약해 보겠습니다.
배워야 합니다

기본 크롤러 작동 원리

기본 http 크롤링 도구, scrapy

Bloom Filter: Bloom Filters by example

웹 페이지를 대규모로 크롤링해야 한다면 분산 크롤러의 개념을 배워야 합니다. 사실 그리 신비롭지는 않습니다. 모든 클러스터 시스템에서 효과적으로 공유할 수 있는 분산 대기열을 유지하는 방법을 배워야 합니다. 가장 간단한 구현은 python-입니다. rq: https://github.com/nvie/rq

rq와 Scrapy: darkrho/scrapy-redis · GitHub

후속처리, 웹페이지 추출(grangier/python-goose · GitHub), 스토리지(Mongodb)


다음은 단편입니다. :

클러스터를 작성하면서 도우반 전체를 내려온 경험을 들려주세요. >1) 먼저 크롤러가 어떻게 작동하는지 이해해야 합니다.
당신이 거미라고 상상해보세요. 그럼 어떻게 해야 할까요? 예를 들어 인민일보의 홈 페이지에서 시작하면 됩니다. $

로 표시됩니다. 인민일보 페이지에 연결되는 다양한 페이지를 볼 수 있습니다. 그러면 '국내 뉴스' 페이지로 크롤링하게 되어 매우 기쁩니다. 두 페이지(홈페이지와 국내 뉴스)의 크롤링이 완료되었습니다. 내려온 페이지를 어떻게 처리할지 고민하지 마세요. 페이지 전체를 html로 복사해서 본문에 올려 놓았습니다.

갑자기 국내 뉴스 페이지에 링크가 있더라구요. "홈페이지"로 돌아갑니다. 똑똑한 거미로서 당신은 이미 그것을 봤다고 해서 뒤로 기어갈 필요가 없다는 것을 알아야 합니다. 따라서 이미 본 페이지의 주소를 저장하려면 두뇌를 사용해야 합니다. 이런 식으로 크롤링이 필요할 수 있는 새로운 링크를 볼 때마다 먼저 마음속으로 해당 페이지 주소를 이미 방문했는지 여부를 확인합니다. 거기 가본 적이 있다면 가지 마세요.

이론적으로는 초기 페이지에서 모든 페이지에 접근할 수 있다면 확실히 모든 웹페이지를 크롤링할 수 있다는 것을 증명할 수 있습니다.

그럼 파이썬에서는 어떻게 구현하나요?
아주 간단함
import Queueinitial_page = "http://www.renminribao.com"url_queue = Queue.Queue()seen = set()seen.insert(initial_page)url_queue.put(initial_page)while(True) :

#모든 것이 손실될 때까지 계속 진행
if url_queue.size()>0:
current_url = url_queue.get() # 대기열의 첫 번째 URL 가져오기
store(current_url) # 저장 이 URL로 표시되는 웹페이지
for next_url in extract_urls(current_url): # 이 URL에 연결된 URL을 추출합니다
if next_url이 보이지 않는 경우:
saw.put(next_url)
url_queue.put( next_url)
else:
break
는 이미 의사 코드로 작성되었습니다.

모든 크롤러의 중추는 여기에 있습니다. 크롤러가 실제로 매우 복잡한 이유를 분석해 보겠습니다. 검색 엔진 회사는 일반적으로 크롤러를 유지하고 개발할 전체 팀을 보유하고 있습니다.

2) 효율성
위 코드를 직접 처리해서 실행시키면 두반 콘텐츠 전체를 크롤링하는데 꼬박 1년이 걸립니다. Google과 같은 검색 엔진이 전체 웹을 크롤링해야 한다는 것은 말할 것도 없습니다.

무엇이 문제인가요? 크롤링해야 할 웹페이지가 너무 많고, 위 코드는 너무 느립니다. 전체 네트워크에 N개의 웹사이트가 있다고 가정하고 재사용 판단의 복잡도는 N*log(N)으로 분석하는데, 이는 모든 웹페이지를 한 번 순회해야 하고 매번 세트를 재사용하려면 log(N) 복잡도가 필요하기 때문입니다. 좋아요, 좋아요, 파이썬의 집합 구현이 해시라는 것을 알고 있습니다. 하지만 여전히 너무 느리고 적어도 메모리 사용량이 효율적이지 않습니다.

일반적으로 체중을 판단하는 방법은 무엇입니까? 간단히 말해서, 여전히 해시 방식이지만, URL이 이미 세트에 있는지 여부를 O(1) 효율성으로 확인하기 위해 고정 메모리(URL 수에 따라 증가하지 않음)를 사용할 수 있다는 것이 특징입니다. 불행하게도 공짜 점심 같은 것은 없습니다. 유일한 문제는 URL이 세트에 없으면 BF는 해당 URL을 본 적이 없다고 100% 확신할 수 있다는 것입니다. 하지만 이 URL이 세트에 있으면 다음과 같은 메시지가 표시됩니다. 이 URL은 이미 표시되어야 하지만 불확실성은 2%입니다. 할당한 메모리가 충분히 크면 여기서 불확실성이 매우 작아질 수 있습니다. 간단한 튜토리얼: Bloom Filters by example

이 기능에 주목하세요. URL을 본 경우 작은 확률로 반복해서 볼 수 있습니다(상관없어, 읽어도 지치지 않습니다). 그 이상). 그러나 본 적이 없다면 반드시 보게 될 것입니다(이것은 매우 중요합니다. 그렇지 않으면 일부 웹 페이지를 놓칠 것입니다!). [중요: 이 문단에 문제가 있습니다. 일단 건너뛰세요]


자, 이제 무게 판단을 처리하는 가장 빠른 방법에 가까워졌습니다. 또 다른 병목 현상 - 머신이 하나만 있습니다. 대역폭이 아무리 크더라도 컴퓨터에서 웹 페이지를 다운로드하는 속도에 병목 현상이 발생하는 한 이 속도만 높일 수 있습니다. 하나의 기계로 충분하지 않다면 여러 대를 사용하십시오! 물론 멀티스레딩(Python의 경우 멀티 프로세스)을 사용하여 각 시스템이 최대 효율성에 도달했다고 가정합니다.

3) 클러스터 크롤링
Douban을 크롤링할 때 총 100대가 넘는 머신을 사용하여 한 달 동안 24시간 내내 돌아다녔습니다. 한 대의 머신만 사용한다면 100개월 동안 실행해야 한다고 생각해보세요...

그럼 현재 사용할 수 있는 머신이 100대라고 가정할 때 Python을 사용하여 분산 크롤링 알고리즘을 구현하는 방법은 무엇일까요?

이 100개의 머신 중 더 작은 컴퓨팅 성능을 가진 머신 중 99개를 슬레이브로 호출하고 다른 더 큰 머신을 마스터라고 합니다. 그런 다음 위 코드의 url_queue를 다시 살펴보면 이 큐를 이 마스터 머신에 넣을 수 있습니다. 모든 슬레이브는 네트워크를 통해 마스터와 통신할 수 있습니다. 슬레이브는 웹페이지 다운로드를 완료할 때마다 마스터에게 크롤링을 위해 새 웹페이지를 요청합니다. 슬레이브가 새로운 웹 페이지를 캡처할 때마다 이 웹 페이지의 모든 링크를 마스터의 대기열로 보냅니다. 마찬가지로 블룸 필터도 마스터에 배치되지만 이제 마스터는 방문하지 않은 URL만 슬레이브에 보냅니다. Bloom Filter는 마스터의 메모리에 배치되고, 방문한 URL은 마스터에서 실행되는 Redis에 배치되어 모든 작업이 O(1)임을 보장합니다. (최소 상환액은 O(1)입니다. Redis의 액세스 효율성은 LINSERT – Redis를 참조하세요.)


Python에서 구현하는 방법을 고려하세요.
각 슬레이브에 scrapy를 설치하고, 그러면 각 머신은 크롤링 기능을 갖춘 슬레이브가 되며, 마스터에는 Redis와 rq가 설치되어 분산 큐로 사용됩니다.


그러면 코드는 다음과 같이 작성됩니다.

#slave.py
current_url = request_from_master()
to_send = []
for next_url in extract_urls(current_url):
    to_send.append(next_url)
store(current_url);
send_to_master(to_send)
#master.py
distributed_queue = DistributedQueue()
bf = BloomFilter()
initial_pages = "www.renmingribao.com"
while(True):
    if request == 'GET':
        if distributed_queue.size()>0:
            send(distributed_queue.get())
        else:
            break
    elif request == 'POST':
        bf.put(request.url)

사실, 상상할 수 있듯이 누군가 이미 필요한 것을 작성했습니다: darkrho/scrapy-redis · GitHub

4) Outlook 및 후처리
위에 사용된 "간단한" 방법이 많지만 실제로 상용 규모의 크롤러를 구현하는 것은 쉽지 않습니다. 위의 코드는 큰 문제 없이 전체 웹사이트를 크롤링하는 데 사용할 수 있습니다.

그러나 이러한 후속 처리가 필요한 경우

효과적인 저장(데이터베이스를 어떻게 정리해야 하는지)

유효한 판단(여기서는 웹을 의미함) 페이지 판단) 진심으로, 그것을 복사한 인민일보와 다민일보를 모두 크롤링하고 싶지 않습니다)

효과적인 정보 추출(웹페이지의 모든 주소를 추출하는 방법, "Zhonghua Road, Fenjin Road, Chaoyang District" 등), 검색 엔진은 일반적으로 내가 왜 저장하는지와 같은 모든 정보를 저장할 필요가 없습니다. 사진... .

적시 업데이트(이 페이지가 얼마나 자주 업데이트될지 예측)


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.