2014-12-17 4 views
0

나는 최근에 파이썬을 사용하여 웹 컨텐츠를 긁어 모으는 실험을 해왔다. 나는 크롤러에게 각 웹 사이트의 제목, 본문 내용 및 다른 페이지로 연결되는 모든 링크를 다듬기 시작하는 씨앗을 제공 할 수있었습니다.파이썬으로 효율적으로 웹을 긁어 냄

지금은 모든 링크가 DB에 삽입되는 고유 한 링크인지 확인합니다. 이것은 속도가 느려지지만 필연적 인 기능입니다. 수백 개의 복제본을 가지고 있다는 점은 없습니다.

~ 100 초 안에 페이지를 스크랩하는 것이 실제로 이렇게 느린 프로세스인지, 그리고 그렇다면 어떻게하면 더 빨리 만들 수 있는지 알고 싶습니다. 나는 그 이론에 정말로 관심이있다.

또한 누군가가 더 자세히 살펴보고자하는 경우를 대비하여 코드를 제공 할 것입니다.

import requests as req 
from pymongo import MongoClient 
from bs4 import BeautifulSoup 
import re 
from time import time 
from urllib.parse import urlsplit 

client = MongoClient("ds055980.mongolab.com", 55980) 
db = client.crawler 
db.authenticate("swenn", "password") 

global duplicates, new_links 
duplicates, new_links = 0, 0 
time_list = [] 

def get_data(soup): 
    for script in soup(["script", "style"]): 
     script.extract() 

    if soup.title == None: 
     return False 
    else: 
     title = soup.title.string 

    content = soup.getText(separator=u' ') 
    if len(content) < 15: 
     return False 

    content = content.replace("\n", "") 
    title = title.replace("\n", "") 
    rge = re.compile(r'\s+') 
    content = rge.sub(" ", content) 

    return content, title 


def insert_data_into_db(soup, url): 
    data = get_data(soup) 
    if data == False: 
     db.links.remove({"_id": url[0]}) 
     db.blacklist.insert({"address": url[1]}) 
     return False 

    db.data.insert({"address": url[1], "title": data[1], "content": data[0], "time": round(time()), "in_use": 0}) 


def insert_urls_into_db(soup, current_url): 
    global duplicates, new_links 
    new_links = 0 
    regex = re.compile(r'#.+') 
    link_list = list(set(soup.find_all('a', href = re.compile('.+')))) 

    for link in link_list: 
     url = link.get('href') 

     if "{" in url or "}" in url or "javascript:" in url or "mailto:" in url or url == "#" or url == "": 
      continue 

     if "://" in url: 
      pass 
     elif "//" == url[0::2]: 
      url = "http:" + url 
     else: 
      parsed_current = urlsplit(current_url[1]) 
      if "/" in url[0]: 
       url = parsed_current.scheme+"://"+parsed_current.netloc+url 
      elif "?" in url[0]: 
       url = parsed_current.scheme+"://"+parsed_current.netloc+parsed_current.path+url 
      else: 
       url_sub = current_url[1][::-1] 
       url = url_sub[url_sub.index("/")::][::-1] + url 

     if "#" in url: 
      url = regex.sub("", url) 

     if db.links.find({"address": url}).count() == 0: 
      db.links.insert({"address": url, "time": 1, "in_use": 0}) 
      new_links += 1 
     else: 
      duplicates += 1 

    db.links.update({"_id": current_url[0]}, {"$set": {"in_use": 0, "time": round(time())}}) 

def save_state_and_exit(urls): 
    print("Saving document state...") 
    for url in urls: 
     db.links.update({"_id": url[0]}, {"$set": {"in_use": 0, "time": 1}}) 
     db.data.remove({"address": url[1]}) 
    print("Exiting...") 
    exit() 

def main(): 
    while True: 
     urls = [] 
     try: 
      documents = db.links.find({"time": {"$lt": round(time()) - 2592000}, "in_use": 0}).limit(10) 

      if documents == None: 
       print("Query did not match any documents. Exiting...") 
       break 

      for document in documents: 
       db.links.update({"_id": document["_id"]}, {"$set": {"in_use": 1}}) 
       urls.append((document["_id"], document["address"])) 

      t = round(time()) 

      for url in urls: 
       print("current URL:", url[1]) 
       try: 
        html = req.get(url[1], timeout=5) 
        if html.encoding != 'utf-8': 
         html.encoding = 'utf-8' 
        html = html.text 
       except (req.exceptions.Timeout, req.exceptions.ConnectionError): 
        print("URL",url,"doesn\'t respond. Deleting...") 
        db.links.remove({"_id": url[0]}) 
        if db.blacklist.find({"address": url[1]}).count() == 0: 
         db.blacklist.insert({"address": url[1]}) 
        continue 

       soup = BeautifulSoup(html) 
       if insert_data_into_db(soup, url) == False: 
        continue 

       insert_urls_into_db(soup, url) 

      print("vottis aega:", round(time()) - t,"sekundit","\t","uusi linke:","\t","duplikaate:", duplicates,"\n\n") 
     except (KeyboardInterrupt, SystemExit): 
      save_state_and_exit(urls) 

if __name__ == "__main__": 
    main() 

답변

0

그렇지 않으면 곧 소스 웹 사이트에 의해 차단 될 수 있으며, 크롤러의 설정에서 "DOWNLOAD_DELAY"빠른 거미를 만들기위한 설정 다운로드 지연을 사용을하고 있지만 반드시 웹 사이트는 당신이 할 수 있습니다합니다.

DOWNLOAD_DELAY = 0 //as much as it is possible 
관련 문제