Crawl and Scrap

Материал из KLUG
Перейти к: навигация, поиск

Кравлинг и скрапинг - шпаргалка python

Задача взять данные с одного сайта и передать третьему лицу возникает довольно часто, по крайней мере, спрос на работу такого характера растет, равно как и растет количество сайтов в интернете.

Сбор данных можно разделить на 2 подзадачи:
1. Посетить страничку, получить сырой контент ("Кравлинг")
2. Обработка сырых данных ("Скрапинг")

Для кравлинга была разработана (и не только для кравлинга) mechanize. Также нужно подключить куки и настроить некоторые фичи (напр. обработка редиректов):

import mechanize
import cookielib

br = mechanize.Browser()
cj = cookielib.LWPCookieJar()
br.set_cookiejar(cj)

br.set_handle_equiv(True)
br.set_handle_redirect(True)
br.set_handle_gzip(False)
br.set_handle_referer(True)
br.set_handle_robots(False)
br.set_handle_refresh(mechanize._http.HTTPRefreshProcessor(), max_time=1)
#br.set_debug_http(True)
#br.set_debug_redirects(True)
#br.set_debug_responses(True)

br.addheaders = [('User-agent', 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008071615 Fedora/3.0.1-1.fc9 Firefox/3.0.1')]

Скриптовый броузер мы настроили ("мимикрировали" под файрфокс), посещение странички еще проще:

URL = 'http://some.host/some_uri'
br.open(URL)
res = br.response().read() # html код странички

Если требуется авторизация, вот пример авторизации через форму (<form name="login_form"...><input name="username"...><input name="password"...>):

print YELLOW + 'Logging in...' + ENDC
br.open(LOGIN_URL)
br.select_form('login_form')
br['username'] = 'USERNAME'
br['password'] = 'PASSWORD'
resp = br.submit()

Чтобы удостовериться, что мы залогинились, проверяем, есть ли в ответе сервера ключевая фраза (у каждого сайта - свой способ известить о результате логина, некоторые выводят фразу "Wrong credentials", некоторые "Wrong username/password", кто-то отдает HTTP_ERROR отличный от 200го, кто-то - сообщает в куках).
Пусть в нашем примере сервер просто отдает фразу в html-коде:

if "Wrong username/password" in br.response().read():
  print RED + 'Wrong login/password' + ENDC
  exit()
print GREEN + 'Logged successfully' + ENDC


Ах, да, цвет для терминала:

RED = '\033[31m'
GREEN = '\033[32m'
YELLOW = '\033[33m'
BLUE = '\033[34m'
MAGENTA = '\033[35m'
CYAN = '\033[36m'
ENDC = '\033[0m'

Это был кравлинг: открываем страничку "br.open(URL)", получаем контент "res = br.response().read()".

Теперь скрапинг. Например, обрабатываем табличку, ищем строки в блоке 'div#history', у которых аттрибут содержит row-1 или row-2 (<tr class="row-1"....><tr class="row-2"...>):

from bs4 import BeautifulSoup
import re

for url in URLS:
	try:
	    br.open(url)
	    res = br.response().read()
	    soup = BeautifulSoup(res)
	    divTag = soup.find('div', id='history')
	    trs = divTag.findAll('tr', attrs=re.compile('^row-[12]'))
	except:
	    print RED + 'Cant parse, skipping...' + ENDC
	    continue

Пусть в первой колонке - дата, выведем ее на печать:

for tr in trTags:
    trs = tr.findAll('td')
    date = trs[0].getText().encode('utf-8').strip()
    print date

Вот это и есть скрапинг.

Дальнейшие шаги: сделать скрипт универсальным, например, хранить структуру каждой страницы отдельно, в виде xpath, yaml или json строк.
Создать генератор такого конфига.
В таком случае не нужно править код под каждую страницу.

Личные инструменты
Пространства имён
Варианты
Действия
Навигация
Инструменты