-
Работаем с Твиттером
Как по-быстому связать приложение на Питоне с Твиттером?
Ответ — подключить библиотеку oauthtwitter.
Почему не python-twitter? Потому что первая гораздо меньше по объему кода и числу зависимостей от дополнительных модулей: 300 строк кода против 4000!
Установим необходимые библиотеки:
pip install ouath2 pip install httplib2 pip install simplejson
Для работы с Твиттером нужно зарегистрировать приложение. Твиттер позволяет указывать ссылки вида
localhost
или127.0.0.1
в поле «Callback URL», что очень полезно при разработке на локальной машине.Consumer key — это открытый ключ приложения, что-то вроде логина. Consumer secret — закрытый ключ, которым подписываются запросы к Твиттеру. Если вы где-то опубликовали его, немедленно смените в настройках приложения.
Авторизация в Твиттере проходит в несколько шагов.
Шаг 1: запрос на авторизацию
import oauthtwitter CONSUMER_KEY = "key" SECRET_KEY = "secret" # Инициализация клиента по ключам def sign_init(request): client = oauthtwitter.OAuthApi(CONSUMER_KEY, SECRET_KEY) # Уникальный токен, действительный только для одной авторизации request_token = client.getRequestToken() # Сохраняем токен в сессию пользователя. Можно сохранить на диск или в БД request.session["request_token"] = request_token # Получаем уникальный адрес авторизации на основе токена url = client.getAuthorizationURL(request_token) # Перенаправляем пользователя на страницу ввода пароля return redirect(url)
Шаг 2: ввод логина и пароля на стороне Твиттера
Шаг 3: возврат пользователя на ваш сайт
После авторизации пользователь будет направлен обратно на ваш сайт. Напомню, что в приложении на стадии тестирования у нас указано что-то вроде
http://localhost:8080/twitter/callback
По этому адресу должен быть обработчик, который завершит процесс авторизации.def sign_callback(request): # Извлекаем сохраненный ранее в сессии токен. # Если токена нет, то пусть начинает всё с начала. request_token = request.session.get("request_token") if not request_token: add_message(request, ERROR, u"Request token not found.") return redirect(frontpage) # Ключ валидации запроса из командной строки. oauth_verifier = request.GET.get("oauth_verifier") if not oauth_verifier: add_message(request, ERROR, u"OAuth verifier not found.") return redirect(frontpage) # Снова инициализируем клиента client = oauthtwitter.OAuthApi(CONSUMER_KEY, SECRET_KEY) # Извлечени параметров доступа access_token = client.getAccessToken(request_token, oauth_verifier) print access_token >>> { 'oauth_token_secret': 'xTbNbG0IcUGgng9pyNdy******************', 'user_id': '123123123', 'oauth_token': '78741204-cLgfThwKXuqudeXGTQP***********************', 'screen_name': 'username' }
Отлично! Как видно, access_token представляет из себя словарь со всеми нужными данными: идентификатором и именем пользователя, открытым и закрытым ключами доступа.
Дальнейший сценарий зависит от архитектуры вашего приложения. Например, на основании screen_name заводится новый пользователь (или извлекается имеющийся). Оба ключа записываются в профиль пользователя. Теперь можно работать с Твиттером:
# Инициализация клиента с ключами приложения и пользователя client = oauthtwitter.OAuthApi(CONSUMER_KEY, SECRET_KEY, user_oauth_token, user_oauth_token_secret) # Извлечение твитов пользователя timeline = client.GetUserTimeline() # Твитнуть сообщение client.UpdateStatus("Python testing") # Получить фолловеров timeline = client.GetFollowers()
И так далее, список всех методов ищите в коде класса. Очень доволен этой библиотекой, использую ее в двух проектах.
Комментарии из старого блога
02/11/13 Майя Любимая: я ничего не понимаю
02/20/13 Иван Гришаев: То же самое могу сказать о вашем комментарии.
-
Создание файлов Excel
В статье «Почему форматы Microsoft Office такие сложные?» Джоэл Спольски пишет:
Заставьте Office делать грязную работу за вас. Word и Excel завязаны на сложных объектных моделях, основанных на автоматизации COM, что позволяет программно делать всё, что угодно. Во многих ситуациях проще будет использовать код Office, чем пытаться реализовать его с нуля.
Действительно, если требуется сформировать сложный офисный документ, проще сделать это вызовами API через COM-соединение. Однако, для создания простой эксель-таблички можно задействовать библиотеку xlwt.
Библиотека ставиться просто:
pip install xlwt
Требуется сформировать таблицу с тремя колонками:
- номер лицевого счета абонента, строковый тип;
- дата показания, тип дата;
- показание, тип число.
Проект выполнен на Джанго. Есть модель показания, переданного абонентом:
class Statement(models.Model): user = models.ForeignKey(User) value = models.DecimalField(max_digits=12, decimal_places=6) date = models.DateTimeField(default=datetime.now)
Показания, которые необходимо записать в таблицу, извлекаются следующим образом
statements = Statement.objects.filter(date__range=(t1, t2))
Формирование файла Excel будет выглядеть так:
import xlwt # Определяем формат ячеек для дат date_style = xlwt.XFStyle() date_style.num_format_str = "M/D/YY" # Определяем формат ячеек для чисел num_style = xlwt.XFStyle() num_style.num_format_str = "0.00" wbk = xlwt.Workbook() # Новая книга sheet = wbk.add_sheet("statements") # Новый лист в книге # Добавляем шапку таблицы sheet.write(0, 0, u"Лицевой счет") sheet.write(0, 1, u"Дата") sheet.write(0, 2, u"Показание") # Обход показаний, statements — объект QuerySet из Джанго for i, s in enumerate(statements): # i — индекс итерации, используется как номер строки sheet.write(i+1, 0, s.user.username) sheet.write(i+1, 1, s.date, date_style) sheet.write(i+1, 2, s.value, num_style) # Задаем ширину колонок sheet.col(0).width = 5000 sheet.col(1).width = 5000 sheet.col(2).width = 5000 # Запись файла wbk.save("path/to/file.xls")
-
Запись непойманных исключений в файл
На работе у меня много скриптов, написанных на питоне, и большая часть из них выполняется ночью. Проблема — любой, даже самый надежный скрипт может упасть. Не удалось соединиться с БД, не найден нужный файл, отвалился сетевой ресурс, прислали кривой реестр.
Обрабатывать исключения на каждой операции — утомительно, код распухает на глазах. Гораздо важнее не отлавливать каждую ошибку, а фиксировать факт ее появления и ситуацию, в которой она возникла.
Модуль cgitb устанавливает свой обработчик на всплывающее исключение. Он пишет в файл всю необходимую информацию: дату, время, исключение, его параметры, имя скрипта, фрагмент кода, где было возбуждено исключение и локальные переменные.
Имея эти данные, нетрудно выявить причину ошибки и внести в скрипт нужные коррективы. Модуль очень полезен для CGI-скриптов: ошибки не придется искать в логах Апача, тем более, что такой подробной информации вы там не найдете.
Подключить обработчик очень легко:
import os import cgitb cgitb.enable(display=False, logdir=os.path.dirname(__file__))
logdir — директория, куда будет записан html-файл с информацией об ошибке. В данном примере указана директория, в которой расположен исполняемый скрипт. В CGI-скриптах должна быть указана директория, к которой нет публичного доступа.
При работе с cgitb важно подключать его как можно быстрее, желательно, в начале скрипта. Это поможет обработать ошибки импорта библиотек.
-
Работа с файлами mailbox
Чем хорош почтовый клиент Mozilla Thunderbird?
Хотя бы тем, что хранит письма в удобном формате mailbox. Благодрая этому можно рулить почтой программно: считывать содержимое ящика, удалять и добавлять письма.
Зачем это может понадобитсья? Например, каждый день вам на почту приходят реестры платежей, которые нужно выгрузить из аттача, распаковать, и, в зависимости от имени файла, скопировать в определенную директорию. Напрашивается автоматизация процесса.
В составе богатой библиотеки Питона есть модуль mailbox. Небольшой пример:
import os import cgitb cgitb.enable(display=False, logdir=os.path.dirname(__file__)) import mailbox MAILBOX_PATH = "path/to/mailbox.file" # Путь к файлу ящика DATA_PATH = "store/path" # Директория для файлов mbox = mailbox.mbox(MAILBOX_PATH, create=False) for i, message in enumerate(mbox): attachments = message.get_payload() for attachment in attachments: filename = attachment.get_filename() if filename and filename.endswith(".txt"): body = attachment.get_payload(decode=True) filepath = os.path.join(DATA_PATH, filename) with open(filepath, "w") as f: f.write(body) mbox.remove(i) mbox.close()
Основной цикл обходит все письма в ящике. Переменная attachments — это список частей письма. Частью может быть всё — простой текст, HTML-сообщение, файловое вложение и т.д.
get_filename()
возвращает имя части. Для файлов оно будет отлично от None. Нас интересуют только текстовые файлы. Тело файла извлекается методомget_payload()
части.При передаче файла он может быть закодирован методами base64 или uuencode. Чтобы получить исходный файл, передается параметр
decode=True
. Полученный файл пишется на диск.Сообщение удаляется из ящика. По окончании цикла ящик закрывается.
-
Рассылка смс в Питоне
Отправлять короткие сообщения можно с помощью любого из многочисленных сервисов смс-рассылок.
Я остановил свой выбор на LittleSMS. Низкая фиксированная цена, удобные API, подробная документация, готовые решения для многих языков и платформ.
Работа с сервисом осуществляется по протоколу HTTP GET-запросами. При регистрации вы получите API-ключ. Этим ключом подписываются все запросы. Ключ не является паролем к учетной записи. Если ключ где-то засветился, немедленно смените его в личном кабинете сервиса.
Для Питона рекомендую использовать мою библиотеку с Гитхаба.
Пример работы:
import littlesms # Инициализация класса api = littlesms.Api("user", "API_key") # Проверка баланса. print api.balance() >>> {u'status': u'success', u'balance': 0.5} # Отправка сообщения. print api.send(u"Hello, World!", "7xxxxxxxxxx") >>> { u'count': 1, u'status': u'success', u'recipients': [u'7xxxxxxxxxx'], u'price': 0.5, u'parts': 1, u'test': 0, u'balance': 0.5, u'messages_id': [u'xxxxxx'] } # Отправка сообщения нескольким адресатам с подменой поля «отправитель». recipients = ("7xxxxxxxxx1", "7xxxxxxxxx2", "7xxxxxxxxx3") print api.send(u"Hello, World!", recipients, sender="Anonym") >>> { u'count': 1, u'status': u'success', u'recipients': [u'7xxxxxxxxx1', u'7xxxxxxxxx2', u'7xxxxxxxxx3'], u'price': 0.5, u'parts': 1, u'test': 0, u'balance': 0.5, u'messages_id': [u'xxxxxx1', u'xxxxxx2', u'xxxxxx3'] } # Если компьютер расположен за прокси со сложной схемой авторизации. PROXY = { "proxy": "172.27.86.8", "port": 3128, "user": "ivan", "passw": "secret" } opener = littlesms.curl_opener(**PROXY) api = littlesms.Api("user", "API_key", opener=opener) # Пример работы в облачной платформе App Engine. opener = littlesms.gae_opener() api = littlesms.Api("user", "API_key", opener=opener) # Пример обработки исключения. try: print api.send(u"Hello, World!", "7xxxxxxxxxx", sender="TooLongSender!!!111") except littlesms.ApiError, e: print e >>> Error 7: incorrect sender
Библиотека активно используется больше года в проекте личного кабинета Читинской энергосбытовой компании. На текущий момент отправлено около 15000 сообщений.