Pull to refresh

Оповещение появления нового топика на Хабрахабре с помощью Python

Reading time6 min
Views3K
Мне нравится, когда программа/код полностью своя… понимаешь назначение каждой буквы и почему решение именно такое. В данном топике хочу предложить свой парсер топиков Хабрахабра на Python без сторонних библиотек.
При появлении нового топика — всплывающее окошко сообщает об этом.


Текущий вариант для Linux с GNOME, но 1 строчкой переделывается под Вашу систему.
Работает на словах это так:

1) Скачиваем корневой файл сайта в свой под нужным именем
2) Открываем файл
3) Построчно читаем до нужного момента с названием Блога и отфильтровываем само название
4) Продолжаем читать до момента с названием Топика и отфильтровываем само название
5) То же с датой топика
6) Сравниваем название каждое топика с увиденным последним ранее
7) Если топик не совпал — создаём всплывающее окошко с Блог/Топик/Дата нового топика
8) Если совпали — выходим из программы

Реализуем это на Python (части кода идут последовательно и без вырезок):

Указываем интерпретатор, кодировку, нужные модули и домашнюю папку пользователя, где будут храниться временные файлы (последнее подредактировать под свою систему):
#!/usr/bin/python
# -*- coding: utf-8 -*-

import os, sys
HOME_DIR = "/home/user"


Указываем переменные, нужные для работы скрипта:
LAST_DIR = HOME_DIR + "/.habralast" # файл с названием последнего проверенного топика
HTML_DIR = HOME_DIR + "/.habr.html" # текст корневого файла Хабрахабра
SHOW_FIRST_TIME = 5 # сколько топиков отобразить если скрипт запущен в первый раз
n = 1
new_addr = 0
count = 0


Проверяем запущен ли скрипт в первый раз: если файл .habralast существует — скрипт уже был запущен, иначе — создаём файл с пустой строкой. Переменной topic1 присваеваем название последнего виденного топика и пустую строку если скрипт запущен в первый раз:
if os.path.isfile(LAST_DIR):
	fp = open(LAST_DIR, "r")
	topic1 = fp.readline()
	fp.close()
	last_existed = 1
else:
	fp = open(LAST_DIR, "w")
	topic1 = ""
	fp.close()
	last_existed = 0


Скачиваем Корневой файл Хабрахабра (на заглавной странице отображаются 10 топиков — если пропустили больше: открываем страницу habrahabr.ru/pageN, где N — номер страницы):
while(1):
	if n == 1:
		url = "habrahabr.ru"
	else: url = "habrahabr.ru/page" + str(n) + "/"
	wget = "wget " + url + " -O " + HTML_DIR
	try:
		os.system(wget)
	except:
		print "Cannot connect to server"
		sys.exit()


Открываем полученный текст страницы:
	index = open(HTML_DIR, "r")


В этих строках основа — позже будем построчно читать файл пока не встретим именно такие части:
	s = '				  <a href="http://habrahabr.ru/' # строчка с названием блога
	ss = '						<a' # строчка с названием топика
	sss = '			<div class="published"><!-- Дата в формате ISO пихается в title -->' # строчка с датой написания топика

Убедился много раз, что данные части строк больше нигде не встретятся! Поэтому смело можем это использовать, путанницы не будет.

Проверяем каждую строку по очереди на наличие признака названия блога (2000 взято экспериментально из количества строк в HTML-файле выделенных на топики) и отфильтровав присваеваем его переменной blog:
	for i in range(2000):
		line = index.readline()
		if s in line:
			blog_s = line.find('">')
			blog_e = line.find("</a>")
			blog = line[blog_s+2:blog_e]


Нашли блог — ищем признак названия топика (из кода страницы видно, что топик не дальше 50 строк от блога) и отфильтровав присваеваем его переменной topic. Если топик не совпал в ранее виденным последним (topic != topic1) — записываем новый в файл .habralast, больше такую проверку не делаем, чтоб не записать более поздний топик, т.к. первый новейший:
			for j in range(50):
				line = index.readline()
				if ss in line:
					topic_s = line.find('">')
					topic_e = line.find("</a>")
					topic = line[topic_s+2:topic_e]
					if topic.find("</span>") != -1:
						topic = topic[topic.find("</span>")+7:]
					if topic != topic1:
						if new_addr == 0:
							fp = open(LAST_DIR, "w")
							fp.write(topic)
							fp.close()
							new_addr = 1
						print "Blog:\t" + blog
						print "Topic:\t" + topic

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

Далее снова читаем построчно до появления признака даты топика, не более 100 строк на это надо:
				for k in range(100):
					line = index.readline()
					if sss in line:
						line = index.readline()
						time_s = line.find("<span>")
						time_e = line.find("</span>")
						date = line[time_s+6:time_e]
						print "Date:\t" + date + "\n"
						notify = "notify-send 'Habrahabr.ru: " + blog + "' '" + topic + "\n<i>" + date + "</i>'"
						os.system(notify)
						count += 1
						if count == SHOW_FIRST_TIME and last_existed == 0:
							os.system("rm -f " + HTML_DIR)
							sys.exit()
						break
				break

Строка os.system(notify) создаёт то самое всплывающее окошко с информацией о новом топике. Содержанием оно заполняется строкой выше. Удаляем исходный HTML-файл за ненадобностью и выходим из программы.

Как только нашли последний ранее виденный топик — удаляем HTML-файл и выходим из системы:
					else:
						os.system("rm -f " + HTML_DIR)
						sys.exit()


Это была первая итерация главного цикла. Если пропустили больше топиков, чем есть на первой странице — открываем следующую и всё повторяется:
	n += 1
	index.close()


В среде Gnome за всплывающие окна отвечает команда notify-send. В Вашей системе это может быть по другому. Тогда редактируйте строку с переменной notify = «notify-send 'Habrahabr.ru: » + blog + "' '" + topic + "\n" + date + "'" под Вашу команду с её синтаксисом.

Сдесь я специально не выравнивал строки по левому краю, чтоб понятней было, что после чего идёт и от чего зависит. Подправить пришлось 3-ий код снизу на 2 Tab-а влево, иначе очень не красиво выглядит. Поэтому вот скрипт целиком, чтоб не путаться:
#!/usr/bin/python
# -*- coding: utf-8 -*-

import os, sys

HOME_DIR = "/home/user"

LAST_DIR = HOME_DIR + "/.habralast"
HTML_DIR = HOME_DIR + "/.habr.html"
SHOW_FIRST_TIME = 5
n = 1
new_addr = 0
count = 0

if os.path.isfile(LAST_DIR):
	fp = open(LAST_DIR, "r")
	topic1 = fp.readline()
	fp.close()
	last_existed = 1
else:
	fp = open(LAST_DIR, "w")
	topic1 = ""
	fp.close()
	last_existed = 0

while(1):
	if n == 1:
		url = "habrahabr.ru"
	else: url = "habrahabr.ru/page" + str(n) + "/"
	wget = "wget " + url + " -O " + HTML_DIR
	try:
		os.system(wget)
	except:
		print "Cannot connect to server"
		sys.exit()

	index = open(HTML_DIR, "r")
	s = '				  <a href="http://habrahabr.ru/'
	ss = '						<a'
	sss = '			<div class="published"><!-- Дата в формате ISO пихается в title -->'

	for i in range(2000):
		line = index.readline()
		if s in line:
			blog_s = line.find('">')
			blog_e = line.find("</a>")
			blog = line[blog_s+2:blog_e]

			for j in range(50):
				line = index.readline()
				if ss in line:
					topic_s = line.find('">')
					topic_e = line.find("</a>")
					topic = line[topic_s+2:topic_e]
					if topic.find("</span>") != -1:
						topic = topic[topic.find("</span>")+7:]
					if topic != topic1:
						if new_addr == 0:
							fp = open(LAST_DIR, "w")
							fp.write(topic)
							fp.close()
							new_addr = 1
						print "Blog:\t" + blog
						print "Topic:\t" + topic

						for k in range(100):
							line = index.readline()
							if sss in line:
								line = index.readline()
								time_s = line.find("<span>")
								time_e = line.find("</span>")
								date = line[time_s+6:time_e]
								print "Date:\t" + date + "\n"
								notify = "notify-send 'Habrahabr.ru: " + blog + "' '" + topic + "\n<i>" + date + "</i>'"
								os.system(notify)
								count += 1
								if count == SHOW_FIRST_TIME and last_existed == 0:
									os.system("rm -f " + HTML_DIR)
									sys.exit()
								break
						break
					else:
						os.system("rm -f " + HTML_DIR)
						sys.exit()
	n += 1
	index.close()


Данный скрипт я запускал в терминале, тобишь появлялись и вывод скрипта и всплывающие окошки. Если пользоваться скриптом только в терминале и всплывающие окна Вам не нужны — закомментировать строчку os.system(notify) с 1 предыдущей. Иначе можно разместись команду python path_to_script/HabraParser.py в crontab и вызывать, допустим, каждые 30 минут. А можно и вручную это делать — решение за Вами! Главное подкорректировать директорию, куда будут сохраняться файлы.

Вот как у меня это выглядит внизу экрана при обнаружении нового топика:
image

Вот и всё… помоему удобно!
Tags:
Hubs:
+3
Comments73

Articles