PowerPointアドインを作って、スライドをセクションごとに保存してみた

Python独学ならTech-Joho TOP > いろいろやってみた > PowerPointアドインを作って、スライドをセクションごとに保存してみた

やりたいこと

表記の通りですが、私はOffice2010あたりから追加されたパワーポイントのセクション機能を多用しています。
他にあまり使っている人を見たことがありませんが、コンテンツを文章の章のように分けたいときに便利です。

今回、セクションのあるパワーポイントのスライドの、各セクションを別ファイルとして保存する作業が必要になりました。
そこで、pptxファイルをセクションで分割保存する機能をアドインとして作りました。

マクロは比較的よく作りますが、アドインは初めてなので、その手順をメモして公開します。
言い訳しておきますが、あまり良い設計ではないかもしれません。

必要なツールのインストール

まず、開発の前に、Visual Studio 2017をインストールしました。

次に、プロジェクトを作るにあたって”Microsoft Office Developer Tools”をインストールします。
画面左上の ファイル > 新規作成 > プロジェクト
でウインドウが開くので、左下の 「Visual Studio インストーラーを開く」をクリックします。

開いた「Visual Studio インストーラー」の「製品」タブ内を下のほうにスクロールして「Office/SharePoint開発」を探し、チェックボックスにチェックを入れて、右下の「変更」を押してください。

Office/SharePoint開発のインストール

もしVisual Studioが開いていると、警告が表示されるので、Visual Studioを終了して「実行」を押してください。

インストールが始まります。

インストール完了

インストールが完了したら、「起動」を押してください。

1.プロジェクトを作る

プロジェクトを作ります。

アドインの作成

画面左上の ファイル > 新規作成 > プロジェクト > Office/SharePoint > VSTOアドイン > Powrpoint2013と2016 VTSOアドイン を選択し、名前や場所を適切に変更して、「OK」を押してください。私は「SectionSaver」という名前にしました。

ボタンのクラス

リボンにボタンを作る

まず、リボンデザイナーを使ってリボンを作ります。
画面上日のプロジェクト > 新しい項目の追加 をクリックし、開いたウインドウで、
リボン(ヴィジュアルなデザイナー)を選択して、名前は「Ribbon1.cs」にして、「追加」をクリックします。

リボンのイメージが表示されるので、左側にある「ツールボックス」を開き、「Office リボンコントロール」の中にあるButtonをイメージの適当な場所にドラッグします。

リボンのデザイン

追加したボタンを右クリックし「プロパティ」をクリックし、右下のプロパティ欄を開きます。
「表示」の中の「Label」の欄を「button1」から分かりやすい内容に変更しましょう。

ボタンの作成

次に、作成したRibbon1を、アドインの開始時に表示します。
ThisAddIn.csに、以下のコードを追加してください。

ThisAddIn.cs

        protected override Microsoft.Office.Core.IRibbonExtensibility
CreateRibbonExtensibilityObject()
        {
            
            
            return Globals.Factory.GetRibbonFactory().CreateRibbonManager(
                    new Microsoft.Office.Tools.Ribbon.IRibbonExtension[] { new Ribbon1(this.Application) });
           
        }

セクションを取得して保存する

上のイメージのペイン内にあるボタンをダブルクリックすると、Ribbon1.csのウインドウが開きます。

リボンのクラス

この中の「button1_Click」メソッドに書いた処理が、ボタンのクリック時に実行されます。
以下のように変更しましょう。

Ribbon1.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Office.Tools.Ribbon;
using Microsoft.Office.Interop.PowerPoint;
using System.IO;

namespace SectionSaver
{
    public partial class Ribbon1
    {
        public Microsoft.Office.Interop.PowerPoint.Application application;

        private void Ribbon1_Load(object sender, RibbonUIEventArgs e)
        {

        }

        private void button1_Click(object sender, RibbonControlEventArgs e)
        {
            int firstSlide;
            int slideCount;
            Presentation presentation;
            Slides originalSlides;
            SectionProperties sectionProperties;

            application = Globals.ThisAddIn.Application;
            sectionProperties = application.ActivePresentation.SectionProperties;
            originalSlides = application.ActivePresentation.Slides;

            // 保存用フォルダの準備
            var baseName = application.ActivePresentation.Path + Path.DirectorySeparatorChar + "parts" ;
            bool exists = System.IO.Directory.Exists(baseName);
            if (!exists)
                System.IO.Directory.CreateDirectory(baseName);
            baseName += Path.DirectorySeparatorChar + "my_slide";

          
            // セクションごとの処理
            for (var i = 1; i <= sectionProperties.Count; i++)
            {
                var name =  baseName + i.ToString();

                firstSlide = sectionProperties.FirstSlide(i);
                slideCount = sectionProperties.SlidesCount(i);

                presentation = application.Presentations.Add(Microsoft.Office.Core.MsoTriState.msoFalse);
               
                // 内容とデザインのコピー
                presentation.Slides.InsertFromFile(application.ActivePresentation.FullName, 0, firstSlide, firstSlide + slideCount-1);
                for (var j = 1; j <= presentation.Slides.Count; j++)
                {
                    presentation.Slides[j].Design = originalSlides[firstSlide - 1 + j].Design;
                    
                }
                application.DisplayAlerts = PpAlertLevel.ppAlertsNone;
                presentation.SaveAs(name);
                presentation.Close();



            }
            

        }
    }
}

画面上部の「開始」をクリックして、実行してみましょう。
自動的に、開発中のアドインが読み込まれたパワーポイントが起動します。

「アドイン」タブに、先ほど追加したボタンがあるのでクリックします。
admintab

無事に処理が実行され、セクションごとにファイルがわかれました。

parts files

参考

チュートリアル : 初めての PowerPoint 用 VSTO アドインの作成(microsoft公式)
https://msdn.microsoft.com/ja-jp/library/cc668192.aspx

リボンの概要(microsoft公式)
https://msdn.microsoft.com/ja-jp/library/bb386097.aspx

リボン デザイナー(microsoft公式)
https://msdn.microsoft.com/ja-jp/library/bb386089.aspx

オブジェクトモデル(microsoft公式)
https://msdn.microsoft.com/ja-jp/library/bb772069.aspx

Slides.InsertFromFile メソッド (PowerPoint)(microsoft公式)
https://msdn.microsoft.com/ja-jp/vba/powerpoint-vba/articles/slides-insertfromfile-method-powerpoint

セクション名一覧を取得するPowerPointマクロ
http://www.relief.jp/docs/013931.html

 

Pythonのインストール方法の選択肢 | Django 入門

Python独学ならTech-Joho TOP > django入門 > Pythonのインストール方法の選択肢

どれを選べばいいか

Windows10でDjangoの開発をするにあたって、そもそもPythonをインストールする方法が複数あります。
どれを選べばいいか、一つ一つメリット・デメリットを考えてみます。

主な方法は3つあります。

  1. 公式のWindows版インストーラを使う方法
  2. Pythonに最初から入っている仮想環境ツールvenvを使う方法
  3. 仮想環境ツール&パッケージマネージャーのanacondaを使う方法

結論から言うと、anacondaを使うのが特に初心者には無難な気がします。
(が全く面倒がないわけではありません…)

参考
データサイエンティストを目指す人のpython環境構築 2016

https://qiita.com/y__sama/items/5b62d31cb7e6ed50f02c

Windows版インストーラ

Windows版インストーラのダウンロード

インストーラは下のリンク先からダウンロードできます。

python.org(Pythonの公式ページ)
https://www.python.org/downloads/
「Download Python 3.6.3」をクリックして下さい。

download

Windows版インストーラによるインストール

インストーラをダブルクリックして起動後、「Install Now」をクリックしてください。

install

ウインドウの下にある「Add Python 3.6 to PATH」というチェックボックスは、Pythonの実行ファイルまでのPathを環境変数に追加するか否かを選択するものです。
ここで、ほかにPythonを使う予定がある場合、追加してしまうと、今インストールしているPythonが優先になってしまいます。どうすべきかは状況によります。
このような判断も、仮想環境を使うと必要がなくなるので、インストーラを使う方法は実はおすすめでははありません。

この記事ではチェックを入れないで進むことにします。

また、この手順でインストールされるのは、Pythonの32ビット版です。

「Setup was successful」という画面が表示されたら正常にインストールが完了しています。

Windows版インストーラでインストールしたPythonを使う方法

スタートメニューに「IDLE(Python 3.6 32-bit)」が追加されているはずです。
startmenu

こちらをクリックすると、Pythonと同時にインストールされた簡易的な統合開発環境IDLEが起動します。

こちらには、Pythonを対話的に実行できる、つまりコードを入力してすぐ結果を見ることのできる環境Python 3.6.2 Shellと、ファイルにPythonコードを書いて実行できる機能が含まれています。

Shellrepl

ファイル編集file

Pythonの学習時などに、ちょっと実行してみたいときはShellを、プログラムを開発するときにはファイルの編集機能を使いましょう。

IDLEのファイルの編集画面では、「F5」キーを押すことですぐに実行できて便利です。

プログラムを実行した結果は、このようにShellに表示されます。


file2

*また、もし、インストール時に「Add Python 3.6 to PATH」にチェックを入れていた場合、PowerShellを起動してPythonと入力し、エンターキーを押すとインストールしたPythonが実行されます。

Windows版インストーラで入れたPythonのメリットとデメリット

メリットとして考えられるのはインストールが簡単なことです。
デメリットは複数のPythonをインストールしなければならない状況に対応しずらいことです。
PythonやDjango本体を含めたPythonのパッケージは、日々更新されていきますが、それぞれが特定のバージョンに依存しています。
あるアプリを開発した古いPythonの環境を残したまま、別のアプリを新しい環境で構築したい、ということはよくありますが、この方法だけでは対応できません。
また、既にシステムに古いPythonが入っていて、それに依存するソフトウェアがある場合、そのソフトウェアが動かなくなるなどの問題が発生する可能性もあります。
デメリットが大きいので、このPythonをそのまま使用するのは基本的におすすめの方法ではありません。

 

venv

venvはPython3.6に付属の仮想環境管理ツールです。
異なるパッケージのインストールされた仮想環境を複数作ることができます。

venvによる仮想環境の作成方法

Windows PowerShellを開いて、下記を実行します。

> python3 -m venv <仮想環境のパス>

簡単です。
一つ注意点は、venvを利用するには、上記の公式のインストーラでPythonをインストールしておかないといけないということです。
また、異なるバージョンのPythonを利用する方法は私はわかりませんでした…
(virtualenvという非常に普及している別のツールならできます)

参考
28.3. venv — 仮想環境の作成(Pythonの公式ドキュメント)
https://docs.python.jp/3/library/venv.html

venvで作った仮想環境の利用方法

まず、仮想環境をactivate(有効化)します。

> <仮想環境のパス>/bin/activate

この環境でインストールしたパッケージ等は、外の世界のPythonに影響を与えません。

仮想環境から出るにはdeactivateです。

deactivate

実行してみた例です。

 

pwshel

venvメリットとデメリット

venvによって作った仮想環境のPythonを利用するメリットは、インストールしたパッケージが、外の世界のPythonに影響を与えないことです。
開発するアプリケーションごとに仮想環境を作れば、お互いに影響を与えずに開発を進めることができます。
あるアプリで、あるパッケージのバージョンを上げたことで別のアプリが動かなくなる、という事態を防ぐことができます。

デメリットは、最初のPythonは、インストーラで導入する必要がある点です。

Anaconda

AnacondaはPython開発環境が簡単を作ることのできる便利ツール、と私は理解しています。
公式ページのWhat is Anaconda?では、「世界で一番人気のデータサイエンスの基盤」と書いてあるように、Anacondaには、データ解析に便利なツールがたくさん含まれています。
例えばPythonコードを埋め込めるノートアプリJupyter Notebookなどです。

Anaconda公式ページ
https://www.anaconda.com/

ただ、Anacondaはそれ以外にもいろいろな機能があり、仮想環境をつくることもできます。
また、pipの代わりになるパッケージマネージャとしての機能もあります。(pipを併用することも可能)

ただし、いろいろなパッケージを含んでいてとても容量が大きく、インストールも大変で、Djangoの開発環境として要らない機能も多いので、
私は最小構成版のminiconaをおすすめします。

minicondaのダウンロード

minicondaダウンロードページ
https://conda.io/miniconda.html

上記のページからインストーラをダウンロードしましょう。「64-bit (exe installer)」をクリックしてください。

miniconda

minidondaのインストール

ダウンロードしたインストーラをダブルクリックして起動し、基本的に「next」等を押していけば完了します。

miniconda

minidondaの使い方

インストールが完了したら、スタートメニューに「Anaconda Prompt」が追加されているはずです。

anconda prompot in start menu

クリックして起動しましょう。
基本的にこのAnaconda promptを使ってPythonを実行しましょう。

ここでのPythonの使い方は、venvと似ています。

Anacondaの仮想環境の作成方法

Anaconda promptで、仮想環境をつくりましょう

> conda create -n <仮想環境の名前>

途中で、「Proceed ([y]/n)?」と聞かれるので、yを押しましょう。
簡単です。

Anacondaの仮想環境の利用方法

Anaconda promptで、以下を実行すると、仮想環境に入ることができます。

> activate <仮想環境の名前>

仮想環境からでるにはdeactivateです。

> dactivate 

一通り実行してみました。anacondashell

Anacondaのメリットとデメリット

Anacondaのメリットは、venvのメリットがすべてに加えて、最初にPythonをインストールしなくてもよいところです!
あと、仮想環境ではpython自体のバージョンも変えることができます。
デメリットとしては、Djangoアプリケーション開発環境としてはいらないもの(Jupyter notebookなど)が入ってしまう点でしょうか。
ただ、全体としてはAnacondaが一番すっきりした環境だと感じます。

結論

というわけで、3つの環境を見た結果、Anaconda promptが一番のような気がします。

Joy-Conを直接充電できるようにした

Python独学ならTech-Joho TOP > いろいろやってみた > Joy-Conを直接充電できるようにした

訳あってスイッチのJoy-Conだけを買いました。

SwitchのJoy-Conは、PCにBluetooth接続すればゲームパッドとして認識されるので、Steamのゲームなんかで使うことができます。

参考


ただ、本体や充電グリップを持っていないと充電することができません。

充電グリップも高いので買いたくないため、JoyCon単体で充電できるようにしてみました。

開ける

Y型のドライバーが必要です。

下みたいいなのでもいいし、ホームセンターにの精密ドライバセットを買えばいいだけのような気がします。

Joy-Con全体

このへんなどにねじがあります。
Joy-Conネジ

全部で4つ、y字のドライバーで外します。
Joy-Conネジを外した

Joy-Con開けた

線をつなげる

こんな感じにつなげます。
はんだ付けがへたくそで恥ずかしいです。

Joy-Con充電用はんだ付け2

Joy-Con充電用はんだ付け

Joy-Conのコネクタが有る側の、上から4番目のピンが+で、右側にあるのがグランドです。
ここから線を引き出して外に出せばいいです。

参考
http://kako.com/blog/?p=24582
上のサイトの方がちゃんと端子を付けてますが、私は持っていなかったので線をただはんだ付けして外にだしただけです。

参考
https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering
こちらの方はリモコンをリバースエンジニアリングした結果をgithubに公開しています。
充電用の端子が4番ピン、つまり左から4番目らしいです。

蓋を閉めると、こんな感じに
Joy-Con充電線がでてる

充電する

定格がわからないのですが上の記事の方が5V、0.2Aで充電されているので、こちらを参考にします。
リバースエンジニアリングの結果の記事でも5Vというのは共通しています。

適当にRaspberry pie3の5Vの端子につないで、30分ほど放置してみました。

すると、無事充電できたようです。

ただし、Joy-Conのホームボタン?を押すとラズパイが落ちるという現象が発生するようになった。
どういうことはわかりませんが、電流が逆流してるのだろうか???

Django 1.11 モデルの追加とマイグレーション | Django 入門

Python独学ならTech-Joho TOP > django入門/ > Django 1.11 モデルの追加とマイグレーション

Djangoでモデルを追加する

 

こちらのDjango公式チュートリアル (バージョン1.11用)をやってみます。

https://docs.djangoproject.com/ja/1.11/intro/tutorial02/

そのままやっても意味がないので、モデル名を変えてみます。

初心者の方は、両方を見比べることで、どのようにモデルを作ればいいのかがわかると思います。

基本的に、こちらの記事の続きです。

Windows 10 でDjango入門

設定

アプリ名は

“djangoTestApp”

だとします。

データベース名は

“django_test_app”

です。

データベース設定

mysqlにログインして

CREATE DATABASE django_test_app;

djangoTestApp2/settings.py

DATABASES = {
  'default': {
    #'ENGINE': 'django.db.backends.sqlite3',# もともとの設定
    'ENGINE': 'django.db.backends.mysql',
    #'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), # もともとの設定
    'NAME': 'django_test_app',
    'USER': 'xxxx',
    'PASSWORD': 'xxxx',
    'HOST': '127.0.0.1'
  }
}

上記のような書き方は、settings.pyの一部を表す。
例えば、上の例は76行目付近だった。
settings.pyを開いて、DATABASES等で検索して該当箇所まで移動して修正すること。

もしくは、設定ファイルを別に用意して使う
参考

https://docs.djangoproject.com/ja/1.11/ref/databases/#mysql-notes

djangoで使えるmysqlのアダプタはいくつかある

python3で推奨されているmysqlclient にする
参考

コンソール

> pip3 install mysqlclient

コンソールというのは、windows power shellや、コマンドプロンプトのこと
>の行の内容を入力する

ついでに、タイムゾーンと言語設定

djangoTestApp/settings.py

#LANGUAGE_CODE = 'en-us'
LANGUAGE_CODE = 'ja-jp'
#TIME_ZONE = 'UTC'
TIME_ZONE = 'Asia/Tokyo'

タイムゾーンのリスト
https://en.wikipedia.org/wiki/List_of_tz_database_time_zones

マイグレーション実行の方法

コンソール

> python manage.py migrate

Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying sessions.0001_initial... OK

こんな感じの表示が出たら成功

 

モデル作成

もともとのチュートリアルは投票アプリケーションらしく、
Question(投票項目)とChoice(選択肢)という2つのモデルを定義する

同じ例ではつまらないので、はてなブックマークのようなソーシャルブックマークサービスを想定する
Article(記事)とBookmark(ブックマーク)
ブックマークにはstar(スター)をつける

アプリ作成からやりなおす

>  python manage.py startapp bookmaker

bookmaker/urls.py
をつくり
djangoTestApp/urls.pyを修正する

仮のER図はこちらです。
ER図(articleとbookmark)

djangoのDB変更は3ステップ

  • models.pyを変更
  • python manage.py makemigrations でマイグレーションファイルを作成
  • python manage.py migrate でマイグレーション実行

djangoTestApp/models.py

rom django.db import models


class Article(models.Model):
"""記事"""
summary = models.CharField(max_length=200)
published = models.DateTimeField('date published')


class Bookmark(models.Model):
"""ブックマーク"""
article = models.ForeignKey(Article, on_delete=models.CASCADE)
comment = models.CharField(max_length=200)
stars = models.IntegerField(default=0)

djangoTestApp/settings.py

INSTALLED_APPS = [
  'bookmarker.apps.BookmarkerConfig',
  'django.contrib.admin',
  'django.contrib.auth',
  'django.contrib.contenttypes',
  'django.contrib.sessions',
  'django.contrib.messages',
  'django.contrib.staticfiles',
]

モデルを確認して、マイグレーションファイルを作成する

> python manage.py makemigrations bookmarker
Migrations for 'bookmarker':
  bookmarker\migrations\0001_initial.py
    - Create model Article
    - Create model Bookmark

0001というマイグレーションができた

できたマイグレーションの内容を確認

> python manage.py sqlmigrate bookmarker 0001
BEGIN;
--
-- Create model Article
--
CREATE TABLE `bookmarker_article` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `summary` varchar(200) NOT NULL, `published` datetime(6) NOT NULL);
--
-- Create model Bookmark
--
CREATE TABLE `bookmarker_bookmark` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `comment` varchar(200) NOT NULL, `stars` integer NOT NULL, `article_id` integer NOT NULL);
ALTER TABLE `bookmarker_bookmark` ADD CONSTRAINT `bookmarker_bookmark_article_id_8c3fd859_fk_bookmarker_article_id` FOREIGN KEY (`article_id`) REFERENCES `bookmarker_article` (`id`);
COMMIT;

CREATE TABLEのSQL文がふたつ

> python manage.py migrate

実行された

 

Shellでモデルの使い方の確認

シェル起動

> python manage.py shell

いろいろなメソッドを使ってみる

>>> from bookmarker.models import  Article
>>> Article.objects.all()

>>>
>>> from django.utils import timezone
>>> a = Article(summary='This is the first article.', published=timezone.now())
>>> a.save()
>>> a.id
1
>>> a.summary
'This is the first article.'
>>> a.published
datetime.datetime(2017, 10, 11, 4, 11, 25, 212888, tzinfo=)
>>> Article.objects.all()
]>

モデル一覧を見てみたが、(Article.objects.all())中身がぜんぜんわからないので、表示設定をする

 

モデルに表示設定など追加
models.py

import datetime
from django.db import models
from django.utils import timezone

class Article(models.Model):
  """記事"""
  summary = models.CharField(max_length=200)
  published = models.DateTimeField('date published')

  def __str__(self):
    return self.summary

  def was_published_recently(self):
    return self.published >= timezone.now() - datetime.timedelta(days=1)

  class Bookmark(models.Model):
  """ブックマーク"""
  article = models.ForeignKey(Article, on_delete=models.CASCADE)
  comment = models.CharField(max_length=200)
  stars = models.IntegerField(default=0)

  def __str__(self):
    return self.comment

__str__というメソッドをそれぞれ追加した。

もう一回シェルを立ち上げて確認する

> python manage.py shell

モデルのいろいろな使い方を確認してみる
検索、取得、作成、削除など..

>>> from bookmarker.models import  Article
>>> Article.objects.all()
]>
>>> Article.objects.filter(id=1)
]>
>>> Article.objects.filter(summary__startswith='This')
]>
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Article.objects.get(published__year=current_year)

>>> Article.objects.filter(id=2)

>>> Article.objects.get(id=2)
Traceback (most recent call last):
  File "", line 1, in 
 略
    self.model._meta.object_name
bookmarker.models.DoesNotExist: Article matching query does not exist.

>>> a1 = Article.objects.get(pk=1)
>>> a1.was_published_recently()
True
>>> a1.bookmark_set.all()

>>> a1.bookmark_set.create(comment='good!', stars=0)

>>> a1.bookmark_set.create(comment='bad', stars=10)

>>> b3 = a1.bookmark_set.create(comment='???', stars=2)
>>> b3.comment
'???'

>>> Bookmark.objects.filter(article__published__year=current_year)
, , ]>

>>> b3.delete()
(1, {'bookmarker.Bookmark': 1})
>>> Bookmark.objects.filter(article__published__year=current_year)
, ]>

 

管理画面

管理ユーザ作成

> python manage.py createsuperuser
Username (leave blank to use 'xxxx'): admin
Email address: admin@example.com
Password:
Password (again):
This password is too short. It must contain at least 8 characters.
This password is too common.
Password:
Password (again):
Superuser created successfully.

最初passにしようとしたらtoo short too commonと怒られた。
passpassにしたら通った。これでいいのか?

アプリ起動

> python manage.py runserver

http://localhost:8000/admin
にアクセス
Django管理サイトのログイン画面

ログイン後
Django管理サイトログイン後

追加したモデルを管理対象にする

bookmaker/admin.py

from django.contrib import admin

# Register your models here.
from .models import Article, Bookmark

admin.site.register(Article)
admin.site.register(Bookmark)

もう一回アクセス
管理対象のモデル一覧

Articlesをクリック
Article一覧

This is the first article.をクリック

Article管理

ちゃんとタイムゾーンで指定した通り、日本時間で表示されている

MySQLのDB内を直接のぞくと、UTCになっている

DBの中身

ちなみに、MySQL Workbenchを使っている
https://www.mysql.com/jp/products/workbench/

20日に変更して保存
Article20日に日付変更

これでチュートリアル2は終わり

 

おまけ: Herokumへのデプロイ

デプロイの手順の記事

Django 1.11 Herokuでデプロイ

Python独学ならTech-Joho TOP > django入門/ > Django 1.11 Herokuでデプロイ

Herokuは無料枠もあるPaasです。
Djangoで作ったWebアプリケーションを無料で公開できます。

Ruby on Railsではよく使っていましたが、Djangoは初めてだったので試してみました。

参考
https://qiita.com/Shitimi_613/items/6627d0ce042d38b86893

アプリはこちらのやつ
Django 1.11 モデルの追加とマイグレーション

windows上で開発しているので、関連箇所あり。

> pip install django-toolbelt

Procfileを作成

web: gunicorn djangoTestApp2.wsgi --log-file -

runtime.txtを作成

python-3.6.2

requirements.txtを作成

pip freeze > requirements.txt

この後、pywin23の行を削除する
そのほか、pipにいらないパッケージがあった場合も削除
いるものだけ書けばよい

settings.py に追記

STATICFILES_DIRS = (
  os.path.join(BASE_DIR, 'static'),
)
# DATABASES~の下あたりに追記
import dj_database_url
db_from_env = dj_database_url.config(conn_max_age=400)
DATABASES['default'].update(db_from_env)

djangoTestApp/wsgi.pyを変更

import os

from dj_static import Cling # これ追記
from django.core.wsgi import get_wsgi_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djangoTestApp.settings")

application = Cling(get_wsgi_application()) # ここ変更

Herokuのツールのインストール
https://devcenter.heroku.com/articles/heroku-cli

herokuでログイン

> heroku login
Enter your Heroku credentials:
Email: xxxx@xxxxx.net
Password: ************
Logged in as xxxx@xxxx.net

herokuのプロジェクト作成

> heroku create
Creating app... done, xxxx-xxxx-xxxx
https://xxxx-xxxx-xxxx.herokuapp.com/ | https://git.heroku.com/xxxx-xxxx-xxxx.git

注意!! 以下のようにすれば後々のビルドパックの指定がいらなかった

> heroku create --buildpack heroku/python

ここででてきたアプリのホストを、settings.pyに追加

ALLOWED_HOSTS = [
    'xxxx-xxxx-xxxx.herokuapp.com'
]

よくわからない設定(静的ファイル関係だと思うけど)

heroku config:set DISABLE_COLLECTSTATIC=1

デプロイ

git push heroku master

エラー出た

> git push heroku master
Counting objects: 19, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (17/17), done.
Writing objects: 100% (19/19), 4.91 KiB | 1005.00 KiB/s, done.
Total 19 (delta 0), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote:
remote:  !     No default language could be detected for this app.
remote:                         HINT: This occurs when Heroku cannot detect the buildpack to use for this application automatically.
remote:                         See https://devcenter.heroku.com/articles/buildpacks
remote:
remote:  !     Push failed
remote: Verifying deploy...
remote:
remote: !       Push rejected to salty-river-85500.
remote:
To https://git.heroku.com/xxxx-xxxx-xxxx.git
! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'https://git.heroku.com/xxxx-xxxx-xxxx.git';


webのほうで、Pythonのビルドパックを追加した

Herokuのアプリ管理

ビルドパック追加

再度

git push heroku master

マイグレーション

> heroku run python manage.py migrate


アプリを開く

> heroku open


Pythonのandとor

Python独学ならTech-Joho TOP > Python用語辞典 >Pythonのandとor

andとor

and や orは、TrueやFalse(真偽値)と合わせて、論理演算、ブール演算とはで使う演算子です。
主に、if文の条件を指定する場合に使います。
複数の条件が同時に成り立つ場合(and)や、いずれかしか成り立たない場合(or)を指定することができます。

例えば、「xが1より大きく3より小さい」は下のようになります。

>>> 1 < x and x < 3

別の例だと、「xが10以下、もしくは20以上」は下のようになります。

>>> x <=  10 and 20 <= x 

Pythonのブール演算は少し違う

Pythonのブール演算は、他のプログラミング言語と比べると変わったところがあります。

簡単に箇条書きすると、下のようになります。

  • 数学の記号のように複数条件をつなげて書くことができる。
  • bool型の値(True/False)以外の値を返す

比較をつなげることができる

参考
Python3の公式リファレンス6.10. 比較

説明するより、下の例を見て下さい。

先程あげた、「xが1より大きく3より小さい」という例は、下のものでした。

>>> 1 < x and x < 3

これと、同じ意味の書き方がもう一つあります。

>>> 1 < x < 3

2つのxとandが消えています。
数学のように、「 1 < x < 3」は「xが1より大きく3より小さい」の意味になっています。 xに2など、適当な数字を代入して、下の黒い欄で実行してみてください。 もう一つの例、「xが10以下、もしくは20以上」は1つの書き方しかありません。

>>> x <=  10 and 20 <= x 

bool型以外の値を返す

参考
Python3の公式リファレンス 6.11. ブール演算 (boolean operation)

これは上の内容をそのまま転記します。

式 x and y は、まず x を評価します; x が偽なら x の値を返します; それ以外の場合には、 y の値を評価し、その結果を返します。

式 x or y は、まず x を評価します; x が真なら x の値を返します; それ以外の場合には、 y の値を評価し、その結果を返します。

例を上げて説明しましょう。
「10 or False」がどのように計算され、どのような値を返すか考えてみます。
まず、左の10は、真偽値を判定すると、真になります。
orは、その左の値が真なら左の値を返します。
つまり、この時点で、10は真なので、10が返ることになります。
orの右にあるFalseは、真偽が判定されることもありません。

>>> 10 or False
10

次に、「-1 and 10 > 2」がどのように計算され、どのような値を返すか考えてみます。
まず、左の-1は、真偽値を判定すると、偽になります。
andは、その左の値が偽なら左の値を返します。
つまり、この時点で、-1は偽なので、-1が返ることになります。
abdの右にある10 > 2は、真偽が判定されることもありません。

>>> -1 and 10 > 2
0

場合によって処理を分ける | Python独学ならTech-Joho(10)

Python独学ならTech-Joho TOP > Python入門カリキュラム > 場合によって処理を分ける

If文とは

>や<といった演算子を使ってPythonに式を渡すと、与えられた条件式が成り立つときはTrue(真)、成立しないときはFalse(偽)が返ってきます。
if文は、この診断結果によって、プログラムの流れを変化させることができるものです。

例えば、変数suujiが2より大きいと’2より大きい’、小さいと’2より小さい’と表示するプログラムは以下になります。(下の黒い欄に1行ずついれてみてください。)

>>> suuji = 1
>>> if suuji > 2:
...   print('2より大きい')
... else:
...   print('2より小さい')
... 
'2より小さい'

if suuji > 2:を入れると、>>>となっていたところが…と変化します。
最後の(‘2より小さい’)の行のあとは、1行何もいれないままエンターキーを押して改行してください。

suujiは1なので、常に’2より小さい’が表示されるはずです。

ifの練習1

上の例で、suujiを2, 3, 4, 5にして実行してみてください。何が表示されますか?

値がその都度変わるものを使わないと、if文のありがたさはわかりません。
ユーザの入力を受け付けるinput関数を使う例をみてみましょう。

input関数の使い方はこちらに書いてあります。

>>> nyuuryoku = input('数字を入力して下さい')
>>> suuji = int(nyuuryoku)
>>> if suuji > 2:
...   print('2より大きい')
... else:
...   print('2より小さい')
... 

 


else

if のあとに書く、条件が成立しなかった時に、別の処理が実行させるようにするのが、elseです。
上と同じ例ですが、もう一度見て下さい。

>>> suuji = 1
>>> if suuji > 2:
...   print('2より大きい')
... else:
...   print('2より小さい')
... 
'2より小さい'

suujiという変数に代入されたのは、1です。
ifの後にある条件は、「suujiが2より大きい」です。

すると、ifのあとの条件は成立していません。
その場合、
ifのすぐ下に書いた内容ではなく、ifに続いて書いたelseの後の下に書いた内容が実行されます。

 


elif

elifという、elseとifをくっつけたような文もあります。

上の例を少し変えて、elifという文が真ん中辺りに増えています。
elifの下の部分が実行される条件を日本語にすると、「suujiが2以下で、もし1より大きければ」となります。

>>> suuji = 2
>>> if suuji > 2:
...   print('2より大きい')
... elif suuji > 1:
...   print('1より大きい')
... else:
...   print('1以下')
'2より小さい'

elifは、もし上に書いてある条件が当てはまらかなったら、右に書いてある条件をチェックする、という意味です。
下の例のように、elifをたくさん書くこともできます。

>>> suuji = -2
>>> if suuji > 2:  # 最初の条件
...   print('2より大きい')  
... elif suuji > 1: # 最初の条件が当てはまらかなったらチェックする条件
...   print('1より大きい')
... elif suuji > 0: # 次の条件が当てはまらかなったらチェックする条件
...   print('0より大きい')
... else:  # 上に書いてある条件が全て当ては余らなかったら
...   print('0以下')
'0以下'

この例だと、まず、suujiが2より大きいかをチェックします。(最初の条件)

当てはまらかなったら、suujiが1より大きいかをチェックします。(最初の条件が当てはまらかなったらチェックする条件)

さらに、これも当てはまらかなったら、suujiが0より大きいかをチェックします。(次の条件が当てはまらかなったらチェックする条件)

さらに、これも当てはまらかなったらelseの下に書いてある内容が実行されます。

 

どんどん下の条件に流れていく感じです。


ifの練習2

下の条件を満たすif、elif、elseを使ったコードを黒い欄で実行してみて下さい。

  • input関数を使ってユーザに数字入力させる
  • ユーザが入力した数字をint関数でint型に変換する
  • 変数suujiに、int型に変換した数字を代入する
  • suujiが10より大きかったら’10より大きい’と表示
  • suujiが10以下で、5より大きかったら’5より大きい’と表示
  • suujiが5以下だったら’小さい!!!’と表示

 


andとor

ifの後には、andとorで2つの条件を書くこともできます。

>>> suuji = -2
>>> if suuji > 2 and suuji < 5 :
...   print('5と2の間') 
... else: 
...   print('5以上か、2以下')
'0以下'

くわしくはこちら(執筆中….)で解説する予定です。

 



<< 前へ 第9回 たくさんのデータを1つにまとめる

>> 次へ 第11回 たくさんのデータで同じ処理を繰り返す


input関数|Python用語辞典

Python独学ならTech-Joho TOP > Python用語辞典 > inputで入力を受け付ける

inputで入力を受け付ける

input関数は、その名の通り、ユーザからの入力(input)を受け付ける関数です。
まず、文字で説明するより使ったほうが理解しやすいと思います。
下の黒い欄に、”suuji = input(‘数字を入力して下さい’)”と入力してください。

>>> suuji = input('数字を入力して下さい')

すると、こんな風に、’数字を入力して下さい’と書いたウインドウがでてきます。

Brythonによる入力ダイアログ

入力欄に’1’か何か、数字を入力してOKを押して下さい。
すると、ウインドウが閉じます。

実は、この時点で、suujiという変数に今入力した数値が代入されています。
下のように、print(suuji)と入力してエンターキーを押して下さい。

>>> suuji = input('数字を入力して下さい')
>>> print(suuji)
1

先程入力した数値が表示されます。

input関数の引数

input関数は人間(ユーザ)に入力をさせて、その値を返す関数です。
inputの引数は、入力させるときに表示する文言です。

こうすれば、’何か入力して下さい’と表示されます。

>>> input('何か入力して下さい')

input何か入力して下さい。

こうすれば、’ああああ’と表示されます。

>>> input('ああああ')

inputあああ

下の黒い欄で自分で試してみてください。

inputの引数の練習

ユーザに’アルファベットを入力!!’と表示する、input関数の引数を考えて実行してください。

input関数の戻り値

繰り返しになりますが、input関数は人間(ユーザ)に入力をさせて、その値を返す関数です。
inputの戻り値は、人間が入力した関数です。

下のコードでは、my_inputに、ユーザが入力した値を代入します。

>>> my_input = input('何か入力して下さい')
>>> print(my_input)

なので、my_inputをprintすると、ユーザが入力した文字列が表示されます。

ちなみに、input関数の戻り値は常に文字列になります。
なので、数字を入力しても、数値の文字列になってしまいます。

‘1’ * 5 は 5ではなく、文字列’1’を5こくっつけた’11111’になります。

>>> my_input = input('何か入力して下さい') # 1を入力する
>>> print(my_input * 5)
'11111'

数値として計算したいときは、int関数やfloat関数で、文字列を数値に変換しましょう。

>>> my_input = input('何か入力して下さい') # 1を入力する
>>> int(my_input) * 5
5 

intやfloat等、変数の型についてはこちらをみてください。
変数の型について/

inputの戻り値の練習

ユーザに数値を入力してもらい、それを100倍して表示するプログラムを実行してください。

ふつうのPythonだとウインドウはでてこない

なお、これまで、input関数を実行するとウインドウがでてきましたが、それはこのサイト上でPythonを実行しているときだけの話です。(正確に言うとBrythonをつかっているときだけ)

自分のPCにPythonをインストールして使っている場合、ウインドウはでず、単にinputの引数にしたメッセージが表示されるので、そのまま黒い画面に入力できます。こんな感じです。

>>> message = input('please input!! : ')
please input!! : はーい
>>> print(message)
'はーい'

Pythonで、MySQL5.7のJSON型にツイートを保存してみる

Python独学ならTech-Joho TOP > いろいろやってみた > Pythonで、MySQL5.7のJSON型にツイートを保存してみる

取得したツイートを保存したい

前回、ツイッターから特定のキーワードで検索したツイートを取得するPythonプログラムをつくりました。

Twitterで特定のフレーズで検索して結果を表示する

このままだと、検索したツイートは目でみて確認するだけで終わりで、あとで分析することもできません。ツイートを保存する仕組みが必要です。

MySQLのJSON型を使ってみたい

保存するにはデータベースを使います。しかし、データベースを言ってもいろいろな候補があります。

候補1: MongoDB

取得できるツイートはJSON形式で、リツイートの具合などによって構造は微妙に変わります。こういうときはNoSQLで、MongoDBが最初に思い浮かびました。

ただ、MongoDBは、あまりたくさんのデータを保存するのに向いていないところがあります。やたら容量をくって、えらい目にあった経験があり、余り使いたくありません。

他にもCouchDB、Cassandraなんかもちょっと考えましたが、よく知らないのと調べるのが面倒くさかったのでやめました。

参考

候補2: MySQL

しっかりと、列の構造を決めて、ふつうにMySQLに保存するというのも考えました。しかし、モデルを作るのがめんどくさくてやめました。

JSON型

そこで思い出したのですが、MySQLの列のデータ型で、JSON型というのがあります。

単に一つの文字列型の列にJSON文字列を突っ込むように使えますが、検索などの際、JSONのキーで検索できるようです。

一度使ってみたかったのでこれにします。

MySQL5.6の後半から使えるようになったみたいです。

参考

https://www.webprofessional.jp/use-json-data-fields-mysql-databases/
https://www.s-style.co.jp/blog/2017/06/420/

CRATE文

こうなりました。

CREATE TABLE `tweets` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `content` json NOT NULL,
  `created` datetime DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

datetime型でも、DEFAULT CURRENT_TIMESTAMPで作成時間を入れられるようになったみたいです。
http://dekokun.github.io/posts/2014-05-31.html

MySQLは5.7.21にしました。

Pythonのコード

こうなりました。

from twython import TwythonStreamer, TwythonError
import json
import config
import mysql.connector
import sys


conn = mysql.connector.connect(
    host='localhost',
    port=3306,
    user=config.MYSQL_USER,
    password=config.MYSQL_PASS,
    database='twitter_app'
)

if not conn.is_connected():
    print('could not connect to db')
    sys.exit()
conn.ping(reconnect=True)
cur = conn.cursor()


class MyStreamer(TwythonStreamer):
    def on_success(self, data):
        json_text = json.dumps(data)

        try:
            sql = "insert into tweets (content) values (%s);"
            cur.execute(sql, (json_text,))
            conn.commit()
        except Exception as err:
            conn.rollback()
            print('could not commit inserting:', json_text)
            print('error:', err)
        if 'text' in data:
            print(data['text'])

    def on_error(self, status_code, data):
        print(status_code)


try:
    stream = MyStreamer(config.APP_KEY, config.APP_SECRET, config.ACCESS_TOKEN, config.ACCESS_TOKEN_SECRET)
    stream.statuses.filter(track='AKB')

except TwythonError as e:
    print(e)

configモジュールに、MySQLのパスワードなどいろいろな定数を入れています。

使っているライブラリはmysql-connector-python-rfになりました。mysql-pythonにしようとしたら、変なエラーがでてインストールできませんでした。

$ pip install mysql-connector-python-rf
https://stackoverflow.com/questions/37092125/cant-install-mysql-python-version-1-2-5-in-windows

ツイートの本文だけ取り出す

SELECT
  id,
  content->"$.text" AS `text`
FROM sport_twitter_dev.tweets;

便利です。

Twitterで特定のフレーズで検索して結果を表示するアプリ

Python独学ならTech-Joho TOP > いろいろやってみた > Twitterで特定のフレーズで検索して結果を表示するアプリ

Twitterで特定のフレーズで検索して結果を表示するアプリを作ってみました。

ライブラリ

tweepyはメンテナンスが停止したらしいのでTwthonというライブラリを使います。

Twython公式
https://github.com/ryanmcgrath/twython

Twythonを使う

tweepyについて
http://qiita.com/ogrew/items/0b267f57b8aaa24f1b73

押したキー
http://qiita.com/tobesan/items/d9f4bd543c3a85b49bb2

利用するAPI
Twitter Search
https://developer.twitter.com/en/docs/tweets/search/api-reference/get-search-tweets.html

環境

windows 10
python 3.6.2
virtualenv

準備

 virtualenv有効化

/Users/xxxxxx/.virtualenvs/djangodev/Scripts/activate

Twithonインストール

$ pip install twython

アプリ登録

https://apps.twitter.com/
アプリを登録して、APIキーとAppシークレットを取得
継続的にツイートを取得するためストリームAPIを使いたいなら、アクセストークンとアクセストークンシークレットも取得

コード

.config.py


APP_KEY = 'xxxxxxxxxxxxxxxxx'
APP_SECRET = 'xxxxxxxxxx'
ACCESS_TOKEN = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
ACCESS_TOKEN_SECRET = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'

検索API使うやつ

エンターキーを押すたびに、繰り返し検索する
Search APIを利用
OAuth1が必要

search.py


from twython import Twython, TwythonError
import config

pressed = ''
twitter = Twython(config.APP_KEY, config.APP_SECRET, oauth_version=2)
ACCESS_TOKEN = twitter.obtain_access_token()
twitter = Twython(config.APP_KEY, access_token=ACCESS_TOKEN)

while pressed == '':

    try:
        results = twitter.search(q='プロ野球')
        print('tweets num:', len(results))
        print(results)
    except TwythonError as e:
        print(e)

    pressed = input("type in enter")

print('finish')


ストリーミングAPI使うやつ

継続的にツイートを取得しフィルターする
Streamimg APIを利用
OAhth2が必要

stream.py


from twython import TwythonStreamer, TwythonError

import config

class MyStreamer(TwythonStreamer):
    def on_success(self, data):
        if 'text' in data:
            print(data['text'])

    def on_error(self, status_code, data):
        print(status_code)

try:
    stream = MyStreamer(config.APP_KEY, config.APP_SECRET, config.ACCESS_TOKEN, config.ACCESS_TOKEN_SECRET)
    stream.statuses.filter(track='AKB48')

except TwythonError as e:
    print(e)

 

コードはこちらからもダウンロードできます。
https://github.com/tech-joho-info/GetTweetsByPython