І маленький експеримент щодо написання більш грамотного коду… В мене була ідея перетворювати *.py файли в публікації, а публікації – в виконувані *.py-файли, але поки що ця ідея все ще в статусі ідеї, тому тут просто буде код який можна оформити як пост:
'''
Невеликий скрипт який дозволяє завантажити собі на комп’ютер
який-небудь WordPress блог повністю. До останньої публікації.
Раніше я робив це за допомогою пошуку в ширину, MongoDB, регулярних виразів
і багатьох інших зайвих речей. http://pastebin.com/e4SnvzAX
Зараз, дізнавшись що на wordpress.com є така
річ як sitemap, я можу це робити набагато простіше.
'''
def main():
'''
Звідси програма починає роботу.
Звісно, після того як модуль завантажить всі функції нижче.
'''
# Завантажмо наприклад мій блог:
load_blog('http://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 для головного вмісту сайту якось незручно і варто б це діло автоматизувати. А виявилось що виділення вмісту веб-сторінки – це тонка наука, і є задачею штучного інтелекту. І розв’язується не логічним підходом, а статистичним. Зокрема я накопав наступні роботи:
- 2007, alexjc The Easy Way to Extract Useful Text from Arbitrary HTML
- 2010, Roman Gelembjuk How to extract useful content from HTML page. Приємна несподіванка, автор статті з Франківська.
- 2010, Christian Kohlschütter, Peter Fankhauser and Wolfgang Nejdl: Boilerplate Detection using Shallow Text Features.
Але все це почитавши я подумав що для моїх потреб поки що XPath зійде…
Filed under:
Кодерство,
Павутина Tagged:
блог,
Python