このブログを検索

ラベル python の投稿を表示しています。 すべての投稿を表示
ラベル python の投稿を表示しています。 すべての投稿を表示

2021/07/05

pythonでexcelファイルの正規表現置換をする

 excelの内容を正規表現で置換したかった。

ある列に、数字をカンマで区切った内容を入れてあるのだが、

最後がカンマで終わっている場合、カンマを取りたい。


たとえば、


123, 124, 222, 234

333, 444, 555, 666,

111, 222, 333


みたいな場合、2行目の666, のカンマをとって

333, 444, 555, 666

としたい。


pythonの正規表現は使ったことがあり、

最初は

resut = pattern.match(",$",s1)

という風にしたのだが、なぜかマッチしない。

findallを使ったらマッチした。


置換はもっとスマートな方法があるかもしれないが、

最後の一文字を落とす、という風にした。


###########################
import glob
import os
import openpyxl
import re
import sys


pattern = re.compile('.*,')


bookname = sys.argv[1]

newbook = sys.argv[2]

wb = openpyxl.load_workbook(bookname,data_only=True)

ws = wb[u"Sheet1"]

#print(ws.cell(row=1, column=1).value)


for row in range(1000):
	c1 = ws.cell(row=row+1, column=9)
	if c1.value is None:
		pass
	else:
		s1 = str(c1.value)
		result = re.findall(r",$",s1)
		if result:
			print(str(s1[:len(s1)-1]))
			s2 = str(s1[:len(s1)-1])
			c1.value = s2

wb.save(newbook)
wb.close
##################################

列は9列目(「I列」)を固定で指定。

ファイル名と保存ファイル名は引数で指定

python rep.py filename1 filenmae2

2019/04/20

パスワードを平文で保存してはいけないならどうやって保存するのか?

あるサービスが「パスワードを平文で保存していた」というニュースに対してある有名な人が「平文で保存するなんてありえない!」と怒っていた。

「平文で保存していた」というニュースは何度か見たことがある。

では、平文で保存してはならないのならば、どうやって保存すればいいのか?

そう聞いたら、多くの人がこう答えるだろう。

「暗号化して保存する」

私もそうだと思っていた。

しかしそれは間違いで、正しくは

「パスワードのハッシュを保存する」

であった。


そういうとおそらく「暗号化もハッシュも同じようなものだ、そんな細かいことはどうでもいい」という人も多いだろう。

でも、そういう、「細かいことはどうでもいい」が積み重なって、「平文でも大丈夫」になってしまうのではないだろうか?

だから、ちょっと「細かいこと」にこだわってみよう。

ハッシュとか、暗号化とか、sha1とかmd5とかいうものの存在は知っていた。

ソフトウェアなどをダウンロードしたときにmd5チェックサムがついていて、
ファイルが壊れていないかを確認することができる、とか、

WEBサーバは、sha1は古いアルゴリズムだから、sha256を使わないといけないとか。


しかし、実際に自分がサーバ管理者やサービス提供者になったとして、
顧客のパスワードを安全に保存するにはどうすればいいかと聞かれたら答えられない。

最近、当たり前のことなのだが、知ってちょっと驚いたことがある。

それは、ハッシュというものは同じ値に対してはだれが計算しても同じ結果になる、
ということだ。


windowsのコマンドプロンプト(またはパワーシェル)で、
ハッシュを計算することができる。

別に何かのアプリなどをインストールする必要はない。

a.txt

というファイルがある。
中身は

あいうえお(改行)

で、文字コードをutf-8で保存した。


PS C:\users\taro\desktop> certutil -hashfile a.txt
SHA1 ハッシュ (対象 a.txt):
471399aeda50586bdc982b558bfde1da642c0fb3
CertUtil: -hashfile コマンドは正常に完了しました。

PS C:\users\taro\desktop> certutil -hashfile a.txt md5
MD5 ハッシュ (対象 a.txt):
0f2f3458c1553eb96d499508dc5184b4
CertUtil: -hashfile コマンドは正常に完了しました。

PS C:\users\taro\desktop> certutil -hashfile a.txt sha256
SHA256 ハッシュ (対象 a.txt):
0007a58ae5789f92155f87d6bc51edd4c9b036277d23154fe06a9daf33d0e514
CertUtil: -hashfile コマンドは正常に完了しました。


sha1(デフォルト)、md5、sha256で計算してみた。


それでは、このファイルを、私がさくらのVPSで使っているcentosのサーバにアップロードし、そこでハッシュを計算してみよう。

centosにもハッシュを計算するコマンドがある。

# sha1sum a.txt
471399aeda50586bdc982b558bfde1da642c0fb3  a.txt

# md5sum a.txt
0f2f3458c1553eb96d499508dc5184b4  a.txt

# sha256sum a.txt
0007a58ae5789f92155f87d6bc51edd4c9b036277d23154fe06a9daf33d0e514  a.txt


結果は全く同じである。

ハッシュというのは元の値に対して、人の目からは無意味である程度長く、元の値を推測も計算することもできないような値を生成する。

それはわかっていた。

しかしもうひとつ肝心なことは、同じアルゴリズム(sha1とかmd5とか)を使用すれば、
同じ値からは同じハッシュ値が生成されるということだ。

そうでなければ、たとえばユーザのパスワードのハッシュ値を保存しても、
ユーザのパスワードが正しいかを検証できない。

当たり前のことであるが。


私もパソコン、スマホ、さまざまなインターネット上のサービスなどを利用していて、
「パスワード」というものを何十個、何百個と設定して使用してきたが、
そのパスワードがテキストで読める状態で保存されているのは見たことがない。
パスワードをメールや郵便物に記載して送付されることはあったが。

あらためて、先ほどのcentosのサーバにパスワードがどのように保存されているかを見てみた。

/etc/shadow

というファイルである。

私は複数のアカウントを作成しているが、そのうちいくつかは異なるアカウントに同じパスワードを設定していた。

たとえば、taroというユーザのパスワードが password、
jiroというユーザのパスワードも password
という感じである。

「同じ値のhash値は誰が計算しても同じ」
ということは、taroとjiroのパスワードから計算したhash値は同じ文字列のはずだ......

しかし、実際には違う文字列であった。

あれ?


調べると、パスワードを保存する際にはhash値をもとの文字列からそのまま計算せず、
「ソルト(塩)」と呼ばれるランダムな値を付加して計算するのだそうだ。

その付加する方法は、文字列としてくっつけるのか、二進数でなんらかの演算をするのかわからないが、とにかくもうひと手間加えて、同じパスワードでも同じハッシュにならないようにする。


同じハッシュ値だからといっても、元の値を知ることは事実上不可能なことにはかわりないが、「複数のアカウントが同じパスワードである」という事実があれば、それらのアカウントに使用されているパスワードは誰もが思いつきそうな単純なパスワードであると推測できる。

また、よく使われそうなパスワード文字列を用意し、そのハッシュ値を計算しておいて、
ハッシュ値同士を比較すれば元の文字列がわかる。(これをレインボーテーブルという)

これらを防ぐために、ソルトというものが使われる。

しかし私はそこでひとつ疑問がわいた。

パスワードは正しい値であることを検証しなければならない。


再訪したユーザが入力したパスワード値にソルトを付加してハッシュ値を計算し、保存されたハッシュ値と同じであるかを比較しなければならない。

ではソルトをハッシュ値と一緒に保存するのか。
それは鍵をかけた金庫の横に鍵を置くようなものだ。

/etc/shadowを見てももちろんソルト値は書かれていない...

調べてみた。

ソルト値の隠し場所があった。

金庫のたとえで言うなら、鍵は金庫の横に置かれてこそいないが、
横にテープで貼り付けるくらいのことしかされていなかった。

ソルト値を使ってパスワードからhashを計算したら、
/etc/shadowに書かれているhash値と一致した。

# cat /etc/shadow | grep hiroshi
hiroshi:$6$9Qpwui9R$jrswaF/U2NRgq7Yhuk2YH7T2POuOYuDq/2eH71KMJkRDNaLxHEa25BLvmAnT3zz.ijxv/e6qUK.cEN24FN.GD0:18005:0:99999:7:::

# perl -e 'print crypt("hiroshidesu", "\$6\$9Qpwui9R");'
$6$9Qpwui9R$jrswaF/U2NRgq7Yhuk2YH7T2POuOYuDq/2eH71KMJkRDNaLxHEa25BLvmAnT3zz.ijxv/e6qUK.cEN24FN.GD0


pythonの例

# python -c 'import crypt; print(crypt.crypt("hiroshidesu", salt="$6$9Qpwui9R"))'
$6$9Qpwui9R$jrswaF/U2NRgq7Yhuk2YH7T2POuOYuDq/2eH71KMJkRDNaLxHEa25BLvmAnT3zz.ijxv/e6qUK.cEN24FN.GD0


そもそも、ハッシュ値で保存するのも、さらにその際にソルトを加えるのも、
サーバにアクセスされてかつサーバの管理アカウントでログインされてしまった場合を想定してのことである。

平文で保存していたのも、サーバにログインされないための対策を十分にしているから、
と考えてのことだろう。


sha512の計算方法とか、saltのかけ方とかはわからないが、
それを使ってますよ、というだけで、パスワードの保存方法というのはそんなに難しいことをしているわけではないというのが、分かった。

ただし、繰り返しになるが、それはあくまでも推測したパスワードからハッシュを計算して一致するかを調べる、ということであって、ハッシュ計算の脆弱性があるとか、ハッシュ値から元の値が算出できるとかいうことではない。


※関連エントリ

https://monqy.blogspot.com/2019/04/blog-post_27.html

2019/04/18

pip install mecab-python3 が失敗する

腹立つなァ....

検索してみるとみんな苦労しているようだが、
エラー内容もその対応も様々。



# pip install mecab-python3
Collecting mecab-python3
  Using cached https://files.pythonhosted.org/packages/ac/48/295efe525df40cbc2173748eb869290e81a57e835bc41f6d3834fc5dad5f/mecab-python3-0.996.1.tar.gz
Installing collected packages: mecab-python3
  Running setup.py install for mecab-python3 ... error
    Complete output from command /usr/bin/python3.6 -u -c "import setuptools, tokenize;__file__='/tmp/pip-install-hzcdo768/mecab-python3/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-record-5w7so2s3/install-record.txt --single-version-externally-managed --compile:
    /usr/lib64/python3.6/distutils/dist.py:261: UserWarning: Unknown distribution option: 'long_description_content_type'
      warnings.warn(msg)
    running install
    running build
    running build_py
    running build_ext
    building '_MeCab' extension
    swigging MeCab.i to MeCab_wrap.cpp
    swig -python -shadow -c++ -I/usr/local/include -o MeCab_wrap.cpp MeCab.i
    /usr/local/include/mecab.h:848: Warning(302): Identifier 'set_sentence' redefined by %extend (ignored),
    MeCab.i:88: Warning(302): %extend definition of 'set_sentence'.
    creating build
    creating build/temp.linux-x86_64-3.6
    gcc -pthread -Wsign-compare -DDYNAMIC_ANNOTATIONS_ENABLED=1 -DNDEBUG -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -fPIC -I/usr/local/include -I/usr/include/python3.6m -c MeCab_wrap.cpp -o build/temp.linux-x86_64-3.6/MeCab_wrap.o
    MeCab_wrap.cpp: In function ‘swig_module_info* SWIG_Python_GetModule()’:
    MeCab_wrap.cpp:2452: error: ‘PyCObject_Import’ was not declared in this scope
    MeCab_wrap.cpp: In function ‘void SWIG_Python_SetModule(swig_module_info*)’:
    MeCab_wrap.cpp:2521: error: ‘PyCObject_FromVoidPtr’ was not declared in this scope
    MeCab_wrap.cpp:2512: 警告: unused variable ‘swig_empty_runtime_method_table’
    MeCab_wrap.cpp: In function ‘swig_type_info* SWIG_Python_TypeQuery(const char*)’:
    MeCab_wrap.cpp:2544: error: ‘PyCObject_AsVoidPtr’ was not declared in this scope
    MeCab_wrap.cpp:2549: error: ‘PyCObject_FromVoidPtr’ was not declared in this scope
    error: command 'gcc' failed with exit status 1

    ----------------------------------------
Command "/usr/bin/python3.6 -u -c "import setuptools, tokenize;__file__='/tmp/pip-install-hzcdo768/mecab-python3/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-record-5w7so2s3/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /tmp/pip-install-hzcdo768/mecab-python3/


ログを見てみる。

#### # pip install mecab-python3

実行したコマンド。
コマンドがないとかいうエラーはない。

#### Collecting mecab-python3
####
####   Using cached https://files.pythonhosted.org/packages/ac/48/295efe525df40cbc2173748eb869290e81a57e835bc41f6d3834fc5dad5f/mecab-python3-0.996.1.tar.gz


このtar.gzファイルをダウンロードしてインストールしているようだ。

#### Installing collected packages: mecab-python3
####
####   Running setup.py install for mecab-python3 ... error

で、setup.pyが error になっている。




####     Complete output from command /usr/bin/python3.6 -u -c "import setuptools, tokenize;__file__='/tmp/pip-install-hzcdo768/mecab-python3/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-record-5w7so2s3/install-record.txt --single-version-externally-managed --compile:

以下が setup.pyのエラーの詳細かな。

####
####     /usr/lib64/python3.6/distutils/dist.py:261: UserWarning: Unknown distribution option: 'long_description_content_type'

これはワーニング

####
####       warnings.warn(msg)
####
####     running install
####
####     running build
####
####     running build_py
####
####     running build_ext
####
####     building '_MeCab' extension
####
####     swigging MeCab.i to MeCab_wrap.cpp
####
####     swig -python -shadow -c++ -I/usr/local/include -o MeCab_wrap.cpp MeCab.i


「swigがインストールされていない」という人がいたが、swigはインストールされている。

####
####     /usr/local/include/mecab.h:848: Warning(302): Identifier 'set_sentence' redefined by %extend (ignored),

これもワーニング

####
####     MeCab.i:88: Warning(302): %extend definition of 'set_sentence'.

これもワーニング

####
####     creating build
####

buildを作成

####     creating build/temp.linux-x86_64-3.6
####
####     gcc -pthread -Wsign-compare -DDYNAMIC_ANNOTATIONS_ENABLED=1 -DNDEBUG -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -fPIC -I/usr/local/include -I/usr/include/python3.6m -c MeCab_wrap.cpp -o build/temp.linux-x86_64-3.6/MeCab_wrap.o

gccを呼び出し

####
####     MeCab_wrap.cpp: In function ‘swig_module_info* SWIG_Python_GetModule()’:
####
####     MeCab_wrap.cpp:2452: error: ‘PyCObject_Import’ was not declared in this scope


エラー。PyCObject_Import が宣言されていない。

####
####     MeCab_wrap.cpp: In function ‘void SWIG_Python_SetModule(swig_module_info*)’:
####
####     MeCab_wrap.cpp:2521: error: ‘PyCObject_FromVoidPtr’ was not declared in this scope

エラー。PyCObject_FromVoidPtr が宣言されていない。

####
####     MeCab_wrap.cpp:2512: 警告: unused variable ‘swig_empty_runtime_method_table’

警告。未使用の変数。

####
####     MeCab_wrap.cpp: In function ‘swig_type_info* SWIG_Python_TypeQuery(const char*)’:
####
####     MeCab_wrap.cpp:2544: error: ‘PyCObject_AsVoidPtr’ was not declared in this scope

エラー。PyCObject_FromVoidPtr が宣言されていない。

####
####     MeCab_wrap.cpp:2549: error: ‘PyCObject_FromVoidPtr’ was not declared in this scope

エラー。PyCObject_FromVoidPtr が宣言されていない。

####
####     error: command 'gcc' failed with exit status 1

gccが失敗した。

####
####
####
####     ----------------------------------------
####
#### Command "/usr/bin/python3.6 -u -c "import setuptools, tokenize;__file__='/tmp/pip-install-hzcdo768/mecab-python3/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-record-5w7so2s3/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /tmp/pip-install-hzcdo768/mecab-python3/
####
####
####

違うエラーなのだが、「setup.pyがpython3に対応していない」という人がいる。
多分そんなところだろう。

setup.pyはどこにあるのか。
探すと...

/home/monqy/mecab/mecab/python/setup.py

これはmecab本体かな。

/home/monqy/mecab-python-0.996/setup.py

こっちか。

setup.pyを実行してみるとエラーになる。オプションが必要のようだ。

ログをもう一度見てみると

Complete output from command
/usr/bin/python3.6 -u -c "import setuptools, tokenize;

__file__='/tmp/pip-install-hzcdo768/mecab-python3/setup.py';

f=getattr(tokenize, 'open', open)(__file__);

code=f.read().replace('\r\n', '\n');

f.close();

exec(compile(code, __file__, 'exec'))"

install --record /tmp/pip-record-5w7so2s3/install-record.txt
--single-version-externally-managed
--compile:

多分、最初の方にあるURLからファイルをダウンロード、/tmpに展開し、
そこのsetup.pyを実行している。

/tmp/pip-install-hzcdo768/mecab-python3/

というフォルダはない。
インストールに失敗した後に消しているのだろう。


よーし、では、tar.gzを持ってきて、解凍→インストールしてみよう。

wget https://files.pythonhosted.org/packages/ac/48/295efe525df40cbc2173748eb869290e81a57e835bc41f6d3834fc5dad5f/mecab-python3-0.996.1.tar.gz


ダメ。

swigのバージョンが古いのだろうか。

# swig -version

SWIG Version 1.3.40


でもswigの新しいバージョンの入れ方がわからない。

twitterで、ある人がバージョン指定すればいけると。

pip install mecab-python3==0.7

...いけた。

# pip install mecab-python3==0.7
Collecting mecab-python3==0.7
  Downloading https://files.pythonhosted.org/packages/25/e9/bbf5fc790a2bedd96fbaf47a84afa060bfb0b3e0217e5f64b32bd4bbad69/mecab-python3-0.7.tar.gz (41kB)
    100% |????????????????????????????????| 51kB 2.4MB/s
Installing collected packages: mecab-python3
  Running setup.py install for mecab-python3 ... done
Successfully installed mecab-python3-0.7


とりあえずpythonからmecabが使えるようになった。

ふう。

2019/03/03

python3.6のCGIでGoogleニュースのヘッドラインを抽出するスクレイピング例


python3.6によるスクレイピング例

Googleニュースのヘッドラインのタイトルを抽出する。

beautifulsoupは使わず、正規表現でゴリゴリする。


-------
#!/usr/bin/python
# -*- coding: utf-8 -*-
import requests
import re
import sys
import cgi
import io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')

my_title = 'what\'s hot'

def print_head(title):
    print('Content-type: text/html')
    print()
    print('<html><head>')
    print('<meta http-equiv="Content-Type" content="text/html; charset=utf-8">')
    print('<title>'+title+'</title>')
    print('</head>')

def print_tail():
    print('</html>')

print_head(my_title)

print('<body>')

res = requests.get('https://news.google.com/?hl=ja&gl=JP&ceid=JP%3Aja')
res.raise_for_status()

print("From Google News JP status:" + str(res.status_code) + "<br><br>")

tmp = re.sub('\n','',res.text)
tmp = re.sub('<a href','\n<a href',tmp)
tmp = re.sub('\/a>','/a>\n',tmp)
tmplist = tmp.split('\n')

result = [ s for s in tmplist if re.match('<a href=\"\.\/articles.*?\/a>', s) or ( 'すべての記事' in s ) ]

for i in result:
    if 'すべての記事' in i:
        break
    s = re.sub(r'<a href.*?<span >(.*?)<\/span><\/a>',r'\1',i)
    print(s+"<br>")

print('</body>')

print_tail()

------

苦労したところ

import io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')

これを入れないと、抽出した結果をprintするときに下記のようなエラーになる。

UnicodeEncodeError: 'ascii' codec can't encode characters in position 343-391: ordinal not in range(128)

googleニュースのヘッドラインだけを抽出したかったのだが、
htmlソースを見ても特定の条件がみつからない。

'<a href=\"\.\/articles.*?\/a>',

で抽出すれば見出しのリンクが取れるのだが、ヘッドライン以外もすべて取れてしまう。

「すべての記事」というキーワードが区切りになっているので、
それが出てくるまで、という条件で抽出した。


これができればどこからでもなんでも取れる....








2019/03/02

python3のhello world cgi

最小限のpython cgi

-----
#!/usr/bin/python
# -*- coding: utf-8 -*-

my_title = 'greeting from python'
my_message = 'hello, world'

###

def print_head(title):
    print('Content-type: text/html')
    print()
    print('<html><head>')
    print('<meta http-equiv="Content-Type" content="text/html; charset=utf-8">')
    print('<title>'+title+'</title>')
    print('</head>')

def print_body(message):
    print('<body>')
    print(message)
    print('</body>')

def print_tail():
    print('</html>')

###

print_head(my_title)

print_body(my_message)

print_tail()
-----


3系はprintにカッコをつけてつかう

インデントでスペースとタブを混在させてはいけない


python3をデフォルトにする@centos6

google analyticsがあるcgiがinternal server errorになっていることを報告してきて、
それを直している過程で、

perl (LWP)でやっているスクレイピングが時代遅れ

pythonの2系は時代遅れ

ということを悟ったので、3系(3.6)をインストールした。

2.6とか2.7とかいろいろ入ってしまったのできれいにしようと思ったのだが、
うまく消えないのでとりあえず3系がデフォルトで動くようにした。



# pip install beautifulsoup4
DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7.
Requirement already satisfied: beautifulsoup4 in /usr/local/lib/python2.7/site-packages (4.7.1)
Requirement already satisfied: soupsieve>=1.2 in /usr/local/lib/python2.7/site-packages (from beautifulsoup4) (1.8)
Requirement already satisfied: backports.functools-lru-cache; python_version < "3" in /usr/local/lib/python2.7/site-packages (from soupsieve>=1.2->beautifulsoup4) (1.5)
#


beautifulsoupなる便利なものがあると聞いて使ってみようとしたら「まだ2.7なんか使ってんのかよ」と怒られた。


# python --version
Python 2.6.6


python

とだけやると、2.6.6が起動する。

python3.6

とやれば3系が動くようにはなっているが、面倒。

# python3.6
Python 3.6.7 (default, Dec  5 2018, 15:02:16)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-23)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

"python" はシンボリックリンクなので、
それを3系にリンクしなおせばよい。

# which python
/usr/bin/python

# which python3.6
/usr/bin/python3.6


pipも

# which pip3.6
/usr/bin/pip3.6

# which pip
/usr/local/bin/pip



# ln -s /usr/bin/python3.6 /usr/bin/python
ln: creating symbolic link `/usr/bin/python': ファイルが存在します

現在のリンクを消してから3系へのリンクを作る。

# unlink /usr/bin/python

# ln -s /usr/bin/python3.6 /usr/bin/python



# ln -s /usr/bin/pip3.6 /usr/local/bin/pip
ln: creating symbolic link `/usr/local/bin/pip': ファイルが存在します

pipも同様

# unlink /usr/local/bin/pip
# ln -s /usr/bin/pip3.6 /usr/local/bin/pip




# python
Python 3.6.7 (default, Dec  5 2018, 15:02:16)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-23)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>


# pip -V
pip 9.0.1 from /usr/lib/python3.6/site-packages (python 3.6)


pythonもpipも3系になった。


2016/03/21

block解除時にブラックリストをチェックする

twitterでブロックしたアカウントのブロックを解除するスクリプトを、
毎日動かしている。

私のブロックは本当に迷惑だと感じてするよりも、
フォローしたけどつまらないから外すときにする。

ただフォローをはずすだけならフォローをやめればいいのだが、
ボットとか、フォローされたらすぐフォロー返しする人などの場合、
相手のフォローだけ残ってしまう。

それがいやなのでブロックしている。

しかし、本当にウザい広告とかは永遠にブロックしておきたいので、
ブラックリストを作ってそこに含まれるアカウントはブロック解除しないようにした。


----
import tweepy

consumer_key = 'xxxxxxxxxxxxxx'
consumer_secret = 'xxxxxxxxxxxxxxxx'
access_key = 'xxxxxxxxxxxxxxxxxxx'
access_secret = 'xxxxxxxxxxxxxxxx'

auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_key, access_secret)
api = tweepy.API(auth_handler=auth)
results = api.blocks()

file =open("blacklist.txt").readlines()
blacklist=[]
for line in file:
    line=line.strip("\n")
    blacklist.append(line)

for result in results:
 if result.screen_name in blacklist:
    print 'In black list: ',result.screen_name
 else:
  print 'unblocking ',result.screen_name,'....'
  api.destroy_block(result.id)
----

blacklist.txt というファイルを作って、
ブロックしておきたいアカウント名を改行で区切って書いておく。

それを読んでリストにいれて、
unblockするときにそのリストに含まれていなければ、という条件をつける。

listにappendするときに \n をstripしないとリストの要素に改行文字が含まれてしまう。
そこは改行文字は無視してくれよと思う。
perlはそんなことしないでもバスっとかんたんにリストに読めたような記憶があるが・・・



これを作った後でおもったのだが、
今回はブラックリストを静的につまり手で書いて作ったが、
今後はblockしたアカウントを記録して回数を数えて、
閾値を決めて3回ブロックしたものはunblockしない、
とかしたい。





2015/09/27

python2.7.xを入れたがtweepyが使えない

pythonのスクリプトを実行すると下記のようなメッセージが出てウザい。

# python unblock.py
/usr/lib/python2.6/site-packages/requests-2.7.0-py2.6.egg/requests/packages/urllib3/util/ssl_.py:90: InsecurePlatformWarning: A true SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. For more information, see https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning.
  InsecurePlatformWarning



2.7.xにすれば治ると聞いたのでやってみた。

まず、yum installでは2.6.xが最新といわれてインストールできない。


ファイルをダウンロードしてmake, installする。



まず、makeしたときにいくつかのモジュールがないと言われる。

ないものをインストールするが、どうしてもできないものが残る。


調べると、みんな、「いらないから無視していい」と言っているので、
setup.pyの無視していいところをコメントアウトして、
なんとかインストールできた。


参考にした情報に、「altinstallにしないとダメ」とあったのでそうしたのだが、

すると、pythonが2.6.x と 2.7.xの二つになってしまった。


ただpythonとやると2.6.xが、

python2.7 とやると 2.7.xが動く。


2.7だけでいいのに、と思ったが、
アンインストール方法がよくわからないのでとりあえずそのままにしておく。



ところが、python2.7でスクリプトを実行すると、tweepyがない、といわれる。

tweepyは easy_installで入れたのだが、

たぶん2.6.xでしか使えないようになっているのだろう。


さて、どうすればいいのか・・・・


下記を参考にする。

http://www.petitec.com/2013/04/centos6%E3%81%ABpython2-7%E3%82%92%E5%85%A5%E3%82%8C%E3%82%8B/


wget http://pypi.python.org/packages/source/d/distribute/distribute-0.6.35.tar.gz

tar xzvf distribute-0.6.35.tar.gz

cd distribute-0.6.35

python2.7 setup.py install


easy_install2.7 というのができる。

pipをいれてから、tweepyをいれる。





easy_install-2.7 pip

easy_install-2.7 tweepy



ようやく、あのウザいメッセージが消えるようになった。


2015/05/10

InsecurePlatformWarning

python blocking.py
/usr/lib/python2.6/site-packages/requests/packages/urllib3/util/ssl_.py:90: InsecurePlatformWarning: A true SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. For more information, see https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning.
  InsecurePlatformWarning



warningなので、動くことは動く。

pythonのバージョンを変えれば出なくなるという情報を見つけたが、
それもどうかな。

yum install python

とやると、2.6.6 が入る。


動くから別にいいか、と思ったが、長いのでやっぱりウザい。


1台目ではでなかったのに、とバージョンを見ると 2.7.3 になっている。


いれなおした覚えはあるようなないような・・・


2.7.x をいれてしまえばよさそうだが、

それにともなってアレもアレするとかいう情報が出てくるので、

とりあえず見送り。


2015/05/06

tweepy インストール

yum install python-pip

pip install tweepy

エラーが出る。

# pip install tweepy
Downloading/unpacking tweepy
  Downloading tweepy-3.3.0.tar.gz
  Running setup.py egg_info for package tweepy
    Traceback (most recent call last):
      File "<string>", line 16, in <module>
      File "/tmp/pip-build-root/tweepy/setup.py", line 17, in <module>
        install_reqs = parse_requirements('requirements.txt', session=uuid.uuid1())
    TypeError: parse_requirements() got an unexpected keyword argument 'session'
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):

  File "<string>", line 16, in <module>

  File "/tmp/pip-build-root/tweepy/setup.py", line 17, in <module>

    install_reqs = parse_requirements('requirements.txt', session=uuid.uuid1())

TypeError: parse_requirements() got an unexpected keyword argument 'session'

----------------------------------------
Command python setup.py egg_info failed with error code 1 in /tmp/pip-build-root/tweepy
Storing complete log in /root/.pip/pip.log



ググる。


pip install --upgrade pip

pip install tweepy



2015/04/30

mecab

webサーバも、新しいvpsに移行することにした。

apache + perl がメインである。


mecabを使ったcgiがあるのだが、
perlのmecabがどうしてもインストールできない。

と思ったら、pythonを使ったものになっていたので、
pythonのmecabをインストール

参考
http://d.hatena.ne.jp/mrgoofy33/20110406/1302019908

http://qiita.com/ShingoOikawa/items/175be8a472ec8ed8a707


http://d.hatena.ne.jp/yuboolike/20121207/1354869309


2014/11/09

さくらのVPSにGNS3をインストール(ubuntu)

とりあえず動いた・・・。





centosはメモリ1GBだから、GNS3を動かすのはちょっときついかな。

基本的に下記のガイドのとおり。

https://community.gns3.com/servlet/JiveServlet/download/38-7963/GNS3%20Getting%20Started%20Guide%201.0.pdf


ubuntuには、pythonは2系と3系が両方入っている。

pycrypto とかいうのがインストールされるところでエラーになって、
python2.7-dev と python3.4-dev をいれた。

たぶん3.4だけでいいのだと思う。


2014/10/27

python3ではtweepyが使えない

GNS3のためにpythonを2.x.xから3.x.xにしたら、

今まで動いていた pythonで書いたtwitterのブロックしているユーザ一覧表示スクリプトが

動かなくなった。



調べると、3系ではtweepyは使えず、3系で使える別のライブラリがあるようだ。


作り直しか・・・

2014/01/25

Windowsでpython

twitterでブロックしているユーザの一覧表示およびそのunblockをpythonスクリプトで書いて使っていたのだが、Windows7を再インストールしてその実行環境(そんな大げさなものではないが)を復旧したときのメモ。

pythonをインストールする。

windowsの環境変数で、Pathにpythonをインストールしたディレクトリおよびscriptsディレクトリを追加する。

C:\Python27;C:\Python27\Scripts

tweepyをインストールする。

easy_install tweepy

easy_install は C:\Python27\Scriptsにある。

以上。

2013/06/13

tweepyアップデート

twitterでブロックしているユーザの一覧およびその解除をするpythonのスクリプトが動かなくなっていた。

C:\Users\t>python blocking.py
Traceback (most recent call last):
File "blocking.py", line 18, in <module>
results = api.blocks()
File "build\bdist.win32\egg\tweepy\binder.py", line 185, in _call
File "build\bdist.win32\egg\tweepy\binder.py", line 168, in execute
tweepy.error.TweepError: [{u'message': u'The Twitter REST API v1 will soon stop functioning. Please
migrate to API v1.1. https://dev.twitter.com/docs/api/1.1/overview.', u'code': 68}]


古いAPIのサポートが終わった、みたいなことを見かけたので動かなくなるんじゃないかと予想はしていた。
tweepyを使っているのだが、調べるとtweepyが新しいAPIに対応していたので更新しようとした。

C:\Users\t>easy_install tweepy
Searching for tweepy
Best match: tweepy 1.11
Processing tweepy-1.11-py2.7.egg
tweepy 1.11 is already the active version in easy-install.pth

Using c:\python27\lib\site-packages\tweepy-1.11-py2.7.egg
Processing dependencies for tweepy
Finished processing dependencies for tweepy


が、すでにインストールされています、となる。2.0が出ているのに・・・

easy_installで更新をするには -U をつけるということを知る。

C:\Users\t>easy_install -U tweepy
Searching for tweepy
Reading http://pypi.python.org/simple/tweepy/
Reading http://github.com/tweepy/tweepy
Reading http://github.com/joshthecoder/tweepy
Best match: tweepy 2.0
Downloading http://pypi.python.org/packages/2.7/t/tweepy/tweepy-2.0-py2.7.egg#md5=193993b0df7c4e28fb
a5bb457e401d91
Processing tweepy-2.0-py2.7.egg
Moving tweepy-2.0-py2.7.egg to c:\python27\lib\site-packages
Removing tweepy 1.11 from easy-install.pth file
Adding tweepy 2.0 to easy-install.pth file

Installed c:\python27\lib\site-packages\tweepy-2.0-py2.7.egg
Processing dependencies for tweepy
Finished processing dependencies for tweepy


無事、動くようになった。

その他、不完全ながらphpやperlで作った、webで使えるスクリプトもあるのだがそれらも全部動かなくなっている。

多分同じようにライブラリを更新すればいいのだと思うがメンドクサイからまた今度。

2013/03/10

oauth

oauthは難しい。全然わからん。

perl, php で動くサンプルをマネしてやってきたが、いずれもうまく動かなくなってしまった。

oauthを使うということはつまり、アプリを公開するということである。

自分だけ使うとか、ボットにtweetさせるとかいうだけなら必要ない。

私の場合、ブロックしているアカウントの一覧表示とその解除をしたい。

これだけである。

twitterはblockという機能をあまり使って欲しくないのか、公式ページでは自分が誰をブロックしているのかが簡単にはわからない。私はtwitterで誰かと会話することは皆無といってよいので、ケンカしたり中傷されたりという理由でブロックするのではない。インチキ商売のユーザーとか、フォローしたボットがフォローしてきたが飽きた時とかに使う。

followされるのが嫌なときにもブロックする。ただし、ずっとブロックしたままだとなんだか意識しているようでイヤなので、すぐにブロックを解除する。こうすると、あたかもtwitterの不具合でfollowが外れてしまったかのように見える。

そんなことをしたい。

pythonのtweepyというモジュールでやってみた。

WEBからあるサンプルを見つけて動くことを確認した。

oauthには2組のアカウント(idとパスワードの組み合わせ)を使用する。

consumer key と access token である。

consumer keyはアプリ側で用意しておく。

アプリ利用者は access tokenを取得する必要がある。

このときに自分のtwitterアカウントのIDとパスワードを入力し、access tokenを得て、twitter apiを使用する。




今回参考にしたサンプルでは、2つのスクリプトが動く。

最初のスクリプトではcosumer tokenとsecretを使用して認証のためのURLを取得し、そこにリダイレクトさせる。

http://api.twitter.com/oauth/authenticate?oauth_token=xxxxxx...


アプリを利用するユーザーは自分のtwitterアカウントでログインする。

すると、アプリ開発者が設定したcallback urlにリダイレクトされる。

この時に、callback urlにはoauth_tokenと oauth_verifierというものが付加されている。

アプリケーションは、oauth_tokenと、request secretから request tokenを得、

oauth verifierからaccess tokenを得る。

ここまで来れば、ユーザーにAPIを利用させることができる。

とりあえずaccess tokenを得てapiを動かすことはできるのだが、そのあとでいろいろ困っている。

ブロックしているユーザーの一覧は表示できた。

次にやりたいのはこれらのユーザーのブロック解除である。

ブロック解除するにはそれをおこなう別のスクリプトを動作させる必要がある。

つまり、認証状態を維持して、ブロック解除するスクリプトに渡さねばならないのだ。

どうやるのだろう?クッキーに保存するのか?

このへんはセッション管理で、oauthとはまた別の話か。

自分だけで使うときはaccess tokenをハードコーディングして渡している。

それを動的にやるだけか。

以下がハードコーディングの場合。

import tweepy
consumer_key = '***'
consumer_secret = ' *** '
access_key = ' *** '
access_secret = ' *** '
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_key, access_secret)
api = tweepy.API(auth)
print = api.me().name


tweepy.OAuthHandlerを呼んだ後で、

get_authorization_urlを呼んで認証させると、

oauth_tokenとoauth_verifierが取得できて、

それらを使ってaccess_tokenとaccess_token_secretを得ると。




とりあえず、簡単なセッション管理をした。

access tokenとaccess token secretを取得したらそれをクッキーに保存する。

クッキーにtokenが保存されていたら認証ページへのリダイレクトをせずに、

callback urlへ飛ばす。

access tokenなんかをクッキーに保存すべきじゃないのかな?




2013/03/07

cronだと動かなくなるpythonスクリプト

昨日直したのだがやっぱり動かない。

/var/log/messagesに以下のようなログが。

Mar  7 10:13:01 xxxxxxxx abrt: detected unhandled Python exception in '/hoge/hoge/hoge.py'
Mar  7 10:13:01 xxxxxxxx abrt: can't communicate with ABRT daemon, is it running? [Errno 2] No such file or directory

crontabで指定しているスクリプトは /hoge/hoge/hoge.shで、
/hoge/hoge/hoge.py というのは、sh内で呼んでいるpythonのスクリプトだ。
ルートディレクトリで /hoge/hoge/hoge.sh とやると動く。
hoge.pyを、print文一行だけにすると動く。
ということはpythonスクリプトの内容のせいか。
"No such file or directory" とあるが、何に対してなのか?
スクリプトの内容を変えると動くということは、
スクリプト内で開いているファイルだろう。
でも、ルートディレクトリで /hoge/hoge/hoge.sh とやって問題なく動くからな・・・・
どうしようもない・・・

これも頭の隅においとく。

pythonはいい

pythonはいい。

何がどういいのかを説明するのは難しいが、いろんな新しいアイディアがうかんでそれが即実現できる。

オブジェクトがどうとか型がどうだとかより、それが一番大事なことだ。




2013/03/06

importのエラー

twitterボットのスクリプトをpythonで書いて動くことを確認してcronで動かす。
翌日、動いてないことが発覚した。
python botscript.py だと動くのだが、
実行権限をつけて ./botscript.py とやると、import tweepyがエラーになる。

ImportError: No module named tweepy

sys.path.append('/usr/local/lib/python2.7/site-packages/')

か、と思って追加したがダメ。
見てみると MeCab.py はあるが、tweepy.py がない。 
tweepy-2.0-py2.7.egg というのがある。
tweepy.pyを探すがどこにもない。

あきらめてshスクリプトを作って逃げる。
eggの中のファイルをどっかにコピーすればいけるなんて情報があったが、
そんなことするのはまっぴらゴメンだよ!
python-twitterでやっても同じようになった。
頭の隅において置こう。いつかわかるさ。


今日はほぼ一日中pythonを書いていた。
やっぱり正規表現の使い方がperlと同じようにできないので、ロジックから作り直した。
おおげさかもしれないが、頭の中身がperl脳だったのがpython脳になって混乱している。
文法的に疑問があった時に対話式に確認できるのは便利だな。

user agentの変更

request = urllib2.Request('http://example.com/')
request.add_header('User-agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64)')
response = urllib2.urlopen(request)
html = response.read()