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

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

Цілковите пограбування блогу

with 5 comments

І маленький експеримент щодо написання більш грамотного коду… В мене була ідея перетворювати *.py файли в публікації, а публікації – в виконувані *.py-файли, але поки що ця ідея все ще в статусі ідеї, тому тут просто буде код який можна оформити як пост:

'''
Невеликий скрипт який дозволяє завантажити собі на комп’ютер
який-небудь WordPress блог повністю. До останньої публікації.

Раніше я робив це за допомогою пошуку в ширину, MongoDB, регулярних виразів 
і багатьох інших зайвих речей. http://pastebin.com/e4SnvzAX

Зараз, дізнавшись що на wordpress.com є така 
річ як sitemap, я можу це робити набагато простіше.

'''

def main():
    '''
    Звідси програма починає роботу.
    Звісно, після того як модуль завантажить всі функції нижче.
    '''
    
    # Завантажмо наприклад мій блог:
    load_blog('https://bunyk.wordpress.com/')


def load_blog(url):
    ''' Завантажує блог в піддиректорію поточної директорії '''

    if not url.endswith('/'):
        # На всяк випадок гарантуємо що url закінчується слешем
        url = url + '/'

    # Нехай ім’я блогу - це найдовша частина url (адреса серверу зазвичай)
    blogname = max(url.split('/'), key=len)
    print(blogname)

    # Переконуємось що директорія куди ми завантажуватимемо блог існує.
    checkdir(blogname)

    sitemap = wget(url + 'sitemap.xml')

    # І зберігаємо кожну сторінку про яку пише sitemap:
    for page in iter_pages(sitemap):
        if is_article(page):
            save_page(page, blogname)

def is_article(url):
    ''' Якщо кількість слешів в url менше семи - це не стаття '''
    return sum(1 for c in url if c == '/') >= 7

def save_page(url, blogname):
    ''' Завантажити сторінку блога в файл '''
    name = url_to_name(url)
    print(name)
    with open(blogname + '/' + name, 'w', encoding='utf-8') as f:
        f.write(wget(url).decode('utf-8'))

def url_to_name(url):
    assert isinstance(url, str)
    # прибираємо адресу блогу і слеші з назви сторінки.
    name = ' '.join(url.split('/')[-4:]).strip()

    # розшифрувати кодування з %, якщо в URL кирилиця
    return unquote(name) 

try:
    from urllib.parse import unquote
except ImportError:
    from urllib import unquote


def wget(url):
    ''' Приймає url, повертає вміст того URL в кодуванні сторінки '''
    h, c = http.request(url)
    if h.status == 200:
        return c

''' Завантажувати сторінки будемо за допомогою httplib2 '''
import httplib2
http = httplib2.Http('.cache')


''' Для парсингу sitemap нам потрібна бібліотека для роботи з XML: '''
try:
    from lxml import etree
except ImportError:
    import xml.etree.ElementTree as etree

def iter_pages(sitemap):
    ''' Ця функція перетворює sitemap, даний як байти, на ітератор по url-лах '''

    assert isinstance(sitemap, bytes)

    tree = etree.fromstring(sitemap)

    ''' XPath селектор далі каже нам шукати всі елементи loc, в просторі імен
    sitemap всередині документа. '''
    return (
        element.text for element in
        tree.findall('.//{http://www.sitemaps.org/schemas/sitemap/0.9}loc')
    )


import os
def checkdir(directory):
    ''' Переконатись що директорія існує, а якщо ні - створити '''
    if not os.path.exists(directory):
        os.makedirs(directory)


if __name__ == '__main__':
    main()

Що далі?

Далі було б варто викинути html та залишити лише текст, і провести над ним якісь статистичні дослідження. Але я подумав що щоразу вручну знаходити xpath для головного вмісту сайту якось незручно і варто б це діло автоматизувати. А виявилось що виділення вмісту веб-сторінки – це тонка наука, і є задачею штучного інтелекту. І розв’язується не логічним підходом, а статистичним. Зокрема я накопав наступні роботи:

  1. 2007, alexjc The Easy Way to Extract Useful Text from Arbitrary HTML
  2. 2010, Roman Gelembjuk How to extract useful content from HTML page. Приємна несподіванка, автор статті з Франківська.
  3. 2010, Christian Kohlschütter, Peter Fankhauser and Wolfgang Nejdl: Boilerplate Detection using Shallow Text Features.

Але все це почитавши я подумав що для моїх потреб поки що XPath зійде…

Advertisements

Written by bunyk

Вересень 2, 2013 at 21:44

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

Tagged with ,

Відповідей: 5

Subscribe to comments with RSS.

  1. Для Хаскеля уже давно є Literate Haskell, можливо і для пайтона знайдеться.

    danbst

    Вересень 2, 2013 at 22:09

  2. Дуже сподобався ваш пост – практичний.
    Як вже маякнув @danbst є така концепція (методологія) Literate programming (Кнут ввів) – особливе поєднання коду і документації

    signalpillar

    Вересень 9, 2013 at 09:11


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

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

Лого WordPress.com

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

Twitter picture

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

Facebook photo

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

Google+ photo

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

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

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