Блоґ одного кібера

Історія хвороби контуженого інформаційним вибухом

Домашній http-сервер “Енциклонг”

leave a comment »

Або, про те як я знайшов включені в Python батарейки з вісґі. Тобто нічого додаткового ставити не доведеться.

Знайшов на StackOverflow (Я б сказав який це чудовий сайт, але ви і без мене знаєте.)

Щоб написати цікавий сайт нам потрібно багато контенту, а сервер хочеться спробувати одразу. Тому вирішив піти протореними шляхами, і взяти контент звідти звідки й всі беруть. З інтернету. Але щоб не видавати чистий копіпаст, я зробив заміну “вікі” на “енцикло”, і тепер мій сервер може видавати сторінки Енциклопедії – вільної енциклопедії, та інших сайтів інтернету. Виглядає це так:

Далі я писати не буду, просто покажу і прокоментую код. Читати код – це навіть важливіше ніж читати формули, повірте мені. І раджу звернути увагу що гарний код починається з 49 рядка, а все що до того зроблено аби працювало.

#!coding=utf8
import httplib2
import re
import threading
import webbrowser
from wsgiref.simple_server import make_server

http = httplib2.Http('.cache') # Це буде ще і кешуючий сервер.

PORT = 8080
DOMAIN = 'http://localhost:%s' % PORT
HOME_PAGE = 'http://uk.wikipedia.org/'

def absolute(href):
    ''' Замінює звичайне посилання на почилання через наш сервер '''
    if href.startswith('//'): # Вікіпедія іноді опускає "http". Оптимізація?
        href = 'http:' + href
    return DOMAIN + '/' + href

def site_filter(page, location):
    ''' Заміна тексту сторінок перед видачею '''
    domain = unicode('/'.join(location.split('/')[:3])) # Домен сторінки
    
    def url_subst(match): # Замінити посилання на відносне
        groups = match.groups()
        url = groups[1]
        if not url.startswith(u'//bits.wikimedia.org/'):
            # bits.wikimedia.org викаблучується, тому його не чіпаємо
            if not url.startswith((u'http://', u'//', u'#')):
                url = domain + url
            if not url.startswith(u'#'): # посилання на якорі на сторінці теж
                url = absolute(url)
        return u''.join((
            groups[0],
            url,
            groups[2]
        ))
    page = re.sub(u'(src="|href=")([^"]*)(")', url_subst, page, flags=re.U)

    page = re.sub(u'Вікі', u'Енцикло', page, flags=re.U) # сама суть!
    page = re.sub(u'вікі', u'енцикло', page, flags=re.U)
    return page

def web_filter(page, location):
    ''' Конвертує текст сторінки перед заміною '''
    page = unicode(page, 'utf8') # В Python3 було б легше, я знаю
    return site_filter(page, location).encode('utf8')

def create_response(query):
    ''' Веб-сайт - це функція від HTTP-запиту.'''
    try:
        headers, content = http.request(query)
        content_type = headers['content-type']
    except httplib2.HttpLib2Error, e:
        return 'text/plain', 'Sorry %s' % e
    if 'text/html' in content_type:
        content = web_filter(content, query)
    return content_type, content

def filtering_app(environ, start_response):
    ''' Класичний WSGI application '''
    if environ['REQUEST_METHOD'] == 'GET':
        content_type, response_body = create_response(
            environ['PATH_INFO'][1:] # передаємо туди URI
        )
        status = '200 OK'
        headers = [('Content-type', content_type),
                   ('Content-Length', str(len(response_body)))]
        start_response(status, headers)
        return [response_body]

def open_browser():
    """ Чекає пів секунди, і відкриває сторінку в браузері. """
    def _open_browser():
        webbrowser.open(DOMAIN + '/' + HOME_PAGE)
    thread = threading.Timer(0.5, _open_browser)
    thread.start()

def start_server():
    """ Запускає сервер. """
    httpd = make_server("", PORT, filtering_app)
    httpd.serve_forever()

if __name__ == "__main__":
    open_browser()
    start_server()

А загалом, якщо забути про енциклонгів, то нема простішого способу показати користувачу вашої програми якусь гуйовину, ніж відкрити йому сторінку в браузері, і послати туди згенеровану розмітку. Що б там не казали любителі десктопного програмування.

Advertisements

Written by bunyk

Грудень 18, 2011 at 19:11

Оприлюднено в Кодерство, Павутина

Tagged with

Залишити відповідь

Заповніть поля нижче або авторизуйтесь клікнувши по іконці

Лого WordPress.com

Ви коментуєте, використовуючи свій обліковий запис WordPress.com. Log Out / Змінити )

Twitter picture

Ви коментуєте, використовуючи свій обліковий запис Twitter. Log Out / Змінити )

Facebook photo

Ви коментуєте, використовуючи свій обліковий запис Facebook. Log Out / Змінити )

Google+ photo

Ви коментуєте, використовуючи свій обліковий запис Google+. Log Out / Змінити )

З’єднання з %s

%d блогерам подобається це: