= Краулеры =


{{{#!python
>>> import urllib.request
>>> x = urllib.request.urlopen("http://yandex.ru")
>>> text = x.read()
>>> text[:100]
b'<!DOCTYPE html><html class="i-ua_js_no i-ua_css_standart i-ua_browser_" lang="ru"><head xmlns:og="ht'
}}}

{{{#!python
>>> x = urllib.request.urlopen("http://yandex.ru/yandsearch?text=hello")
>>> text = x.read()
>>> text[:100]
b'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtm'
}}}


{{{#!python
>>> x = urllib.request.urlopen("http://yandex.ru/yandsearch?text=hello")
>>> yatext = x.read()
>>> rutext = yatext.decode("utf-8")
}}}

{{{#!python
>>> import re
>>> re.sub('<[^>]*>', '', rutext)
'\n\n\n\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  -->\n\n  \n  function Focus() {\n      document.getElementById("rep").focus();\n  }\n  \n\n  \n  function ShowText() {\n      var d = document.getElementById("id_captcha_text");\n      d.style.display = (d.style.display == \'block\') ? \'\' : \'block\';\n  }\n  \n  Ой!\n\n\n\n\n\n  \n  \n  \n    \n      \n\n      \n        \n          \n            \n          \n        \n      \n\n      \n\n      \n        \n          \n            &nbsp;\n          \n        \n\n        \n          ой...\n        \n\n        \n          \n            \n              \n            \n          \n        \n      \n\n      \n\n      \n        \n          \n            \n          \n\n          \n            \n          \n\n          \n            \n          \n\n          \n            \n          \n        \n      \n\n      \n    \n    \n  \n  \n  \n  \n    \n      \n\n      \n\n      \n        \n          \nНам очень жаль, но запросы, поступившие с вашего IP-адреса, похожи на автоматические.\nПо этой причине мы вынуждены временно заблокировать доступ к поиску.\nЧтобы продолжить поиск, пожалуйста, введите символы с картинки в поле ввода и нажмите «Отправить».\n\n          \n          \n          \n          \n\n          \n    \n    \n        \n        \n        \n    \n    \n\n\n            \n            \n             \n  \n                \n                \n             \n  \n  \n    \n      \n        \n        \n        \n            \n            Показать другую картинку\n        \n        \n        \n          \n          \n        \n      \n      \n                        В вашем браузере отключены файлы cookies. Яндекс не сможет запомнить вас и правильно идентифицировать в дальнейшем. Чтобы включить cookies, воспользуйтесь советами на странице нашей Помощи.             \n      \n    \n  \n  \n\n            \n            \n          \n\nПочему так случилось?\n\n\n    Возможно, автоматические запросы принадлежат не вам, а другому пользователю, выходящему в сеть с одного с вами IP-адреса.\n    Вам необходимо один раз ввести символы в форму, после чего мы запомним вас и сможем отличать от других пользователей, выходящих с данного IP.\n    В этом случае страница с капчей не будет беспокоить вас довольно долго.\n    Возможно, в вашем браузере установлены дополнения, которые могут задавать автоматические запросы к поиску. В этом случае рекомендуем вам отключить их.\n    Также возможно, что ваш компьютер заражен вирусной программой, использующей его для сбора информации.\n    Может быть, вам стоит проверить систему на наличие вирусов, например, антивирусной утилитой CureIt от «Dr.Web». \n    Если у вас возникли проблемы или вы хотите задать вопрос нашей службе поддержки, пожалуйста, воспользуйтесь\n    формой обратной связи.\n    \n\n\n\n  \n    Если автоматические запросы действительно поступают с вашего компьютера, и вы об этом знаете (например, вам по роду деятельности необходимо отправлять Яндексу\n    подобные запросы), рекомендуем воспользоваться специально разработанным для этих целей сервисом\n    Яндекс.XML.\n\n\n\n        \n      \n\n      \n\n      \n\n      \n    \n  \n  \n  \n  \n    \n    \n      \n        \n\n        \n\n        \n          \n              Обратная&nbsp;связь\n          \n        \n\n        \n          \n              ©&nbsp;1997—2014 «Яндекс»\n          \n        \n\n        \n      \n    \n  \n  \n  \n  \n(function (d, w, c) { (w[c] = w[c] || []).push(function() { try { w.yaCounter10630330 = new Ya.Metrika({id:10630330, webvisor:true, clickmap:true, trackLinks:true, accurateTrackBounce:true, ut:"noindex"}); } catch(e) { } }); var n = d.getElementsByTagName("script")[0], s = d.createElement("script"), f = function () { n.parentNode.insertBefore(s, n); }; s.type = "text/javascript"; s.async = true; s.src = (d.location.protocol == "https:" ? "https:" : "http:") + "//mc.yandex.ru/metrika/watch.js"; if (w.opera == "[object Opera]") { d.addEventListener("DOMContentLoaded", f, false); } else { f(); } })(document, window, "yandex_metrika_callbacks");\n\n  \n\n\n\n'
}}}

{{{#!python
>>> noscript = re.sub('<script[^<]*</script>', '', rutext)
>>> clean = re.sub('<[^>]*>', '', noscript)
>>> re.sub('\s+', ' ', clean)
' --> Ой! &nbsp; ой... Нам очень жаль, но запросы, поступившие с вашего IP-адреса, похожи на автоматические. По этой причине мы вынуждены временно заблокировать доступ к поиску. Чтобы продолжить поиск, пожалуйста, введите символы с картинки в поле ввода и нажмите «Отправить». Показать другую картинку В вашем браузере отключены файлы cookies. Яндекс не сможет запомнить вас и правильно идентифицировать в дальнейшем. Чтобы включить cookies, воспользуйтесь советами на странице нашей Помощи. Почему так случилось? Возможно, автоматические запросы принадлежат не вам, а другому пользователю, выходящему в сеть с одного с вами IP-адреса. Вам необходимо один раз ввести символы в форму, после чего мы запомним вас и сможем отличать от других пользователей, выходящих с данного IP. В этом случае страница с капчей не будет беспокоить вас довольно долго. Возможно, в вашем браузере установлены дополнения, которые могут задавать автоматические запросы к поиску. В этом случае рекомендуем вам отключить их. Также возможно, что ваш компьютер заражен вирусной программой, использующей его для сбора информации. Может быть, вам стоит проверить систему на наличие вирусов, например, антивирусной утилитой CureIt от «Dr.Web». Если у вас возникли проблемы или вы хотите задать вопрос нашей службе поддержки, пожалуйста, воспользуйтесь формой обратной связи. Если автоматические запросы действительно поступают с вашего компьютера, и вы об этом знаете (например, вам по роду деятельности необходимо отправлять Яндексу подобные запросы), рекомендуем воспользоваться специально разработанным для этих целей сервисом Яндекс.XML. Обратная&nbsp;связь ©&nbsp;1997—2014 «Яндекс» '
}}}

== robots.txt ==

{{{#!python
>>> import urllib.robotparser
>>> p = urllib.robotparser.RobotFileParser('http://yandex.ru')
>>> p.can_fetch('urllib', 'http://yandex.ru/yandsearch?text=hello')
True
}}}

{{{#!python
>>> p = urllib.robotparser.RobotFileParser('http://yandex.ru/robots.txt')
>>> p.can_fetch('urllib', 'http://yandex.ru/yandsearch?text=hello')
True
}}}

{{{#!python
>>> p = urllib.robotparser.RobotFileParser('http://yandex.ru/robots.txt')
>>> p.read()
>>> p.can_fetch('urllib', 'http://yandex.ru/yandsearch?text=hello')
False
>>> p.can_fetch('urllib', 'http://yandex.ru/yac2014/')
True
}}}

== Главный цикл ==

{{{#!python
urls = ['http://newsru.com']
for url in urls:
    # fetch page
    # find all urls in page
    #   avoid uninteresting links
    #   avoid links we've already seen
    # add new urls to our list
}}}

{{{#!python
from urllib.request import urlopen
import re

urls = ['http://newsru.com']
for url in urls:
    print(url)
    # fetch page
    file = urlopen(url)
    text = file.read()

    # find all urls in page
    #   avoid uninteresting links
    #   avoid links we've already seen
    # add new urls to our list
}}}

{{{#!python
from urllib.request import urlopen
import re

urls = ['http://newsru.com']
for url in urls:
    print(url)
    # fetch page
    file = urlopen(url)
    text = file.read()
    if 'charset' in file.headers['content-type']:
        charset, = re.findall('charset=(.*)',
            file.headers['content-type'])
    elif b'charset=cp1251' in text:
        charset = 'windows-1251'
    elif b'charset=windows-1251' in text:
        charset = 'windows-1251'
    elif b'charset=utf-8' in text:
        charset = 'utf-8'
    text = text.decode(charset)

    # find all urls in page
    #   avoid uninteresting links
    #   avoid links we've already seen
    # add new urls to our list
}}}

{{{#!python
from urllib.request import urlopen
import re

domain = 'http://newsru.com'
urls = ['http://newsru.com']
for url in urls:
    print(url)
    # fetch page
    file = urlopen(url)
    text = file.read()
    if 'charset' in file.headers['content-type']:
        charset, = re.findall('charset=(.*)',
            file.headers['content-type'])
    elif b'charset=cp1251' in text:
        charset = 'windows-1251'
    elif b'charset=windows-1251' in text:
        charset = 'windows-1251'
    elif b'charset=utf-8' in text:
        charset = 'utf-8'
    text = text.decode(charset)

    # find all urls in page
    for link in re.findall('href=["\']([^"\']*)["\']',
                           text):
        if link.startswith("/"):
            link = domain + link
    #   avoid uninteresting links
        if link.startswith("http://"):
            continue
        if link.startswith("https://"):
            continue            
    #   avoid links we've already seen
        if link in urls:
            continue
    # add new urls to our list
        urls.append(link)
}}}

{{{#!python
from urllib.request import urlopen
from urllib.robotparser import RobotFileParser
import re

domain = 'http://newsru.com'
urls = ['http://newsru.com']
robots = RobotFileParser(domain + '/robots.txt')
robots.read()
for url in urls:
    print(url)
    # fetch page
    # if we may
    if not robots.can_fetch('urllib', url):
        print('denied')
        continue
    file = urlopen(url)
    text = file.read()
    if 'charset' in file.headers['content-type']:
        charset, = re.findall('charset=(.*)',
            file.headers['content-type'])
    elif b'charset=cp1251' in text:
        charset = 'windows-1251'
    elif b'charset=windows-1251' in text:
        charset = 'windows-1251'
    elif b'charset=utf-8' in text:
        charset = 'utf-8'
    text = text.decode(charset)

    # find all urls in page
    for link in re.findall('href=["\']([^"\']*)["\']',
                           text):
    #   avoid uninteresting links
        if link.startswith("http://"):
            continue
        if link.startswith("https://"):
            continue
    #   but still parse the interesting ones
        if link.startswith("/"):
            link = domain + link
        if link.startswith('#'):
            continue
    #   avoid links we've already seen
        if link in urls:
            continue
    # add new urls to our list
        urls.append(link)
}}}

{{{#!python
from urllib.request import urlopen
from urllib.robotparser import RobotFileParser
import re

domain = 'http://newsru.com'
urls = ['http://newsru.com']

def fetch_page(url):
    file = urlopen(url)
    text = file.read()
    charset = detect_charset(file, text)
    retun text.decode(charset)

def detect_charset(file, text):
    if 'charset' in file.headers['content-type']:
        return re.findall('charset=(.*)', file.headers['content-type'])[0]
    elif b'charset=cp1251' in text:
        return 'windows-1251'
    elif b'charset=windows-1251' in text:
        return 'windows-1251'
    elif b'charset=utf-8' in text:
        return 'utf-8'

def add_new_links(text, urls):
    for link in re.findall('href=["\']([^"\']*)["\']', text):
      if is_boring_link(link):
        continue
      link = normalize_link(link)
      if link in urls:
          continue
      urls.append(link)

def normalize_link(link):
    if link.startswith("/"):
        return domain + link
    elif '://' in link:
        return link
    # else ...

def is_boring_link(link):
    if link.startswith("http://"):
        return True
    if link.startswith("https://"):
        return True
    if link.startswith('#'):
        return True

robots = RobotFileParser(domain + '/robots.txt')
robots.read()
for url in urls:
    if not robots.can_fetch('urllib', url):
        print(url)
        text = fetch_page(url)
        add_new_links(text, urls)
    else:
        print(url, 'denied')
}}}

## vim: set et sw=4 ts=4 sts=4: