pythonでxmlを解析

横浜市の防災拠点

from bs4 import BeautifulSoup
import urllib.request as req
import os.path

url = "http://www.city.yokohama.lg.jp/somu/org/kikikanri/data/shelter.xml"
savename = "shelter.xml"
if not os.path.exists(savename):
	req.urlretrieve(url, savename)

xml = open(savename, "r", encoding="utf-8").read()
soup = BeautifulSoup(xml, 'html.parser')

info = {}
for i in soup.find_all("shelter"):
	name = i.find("name").string
	ward = i.find("ward").string
	addr = i.find("address").string
	note = i.find("notes").string
	if not (ward in info):
		info[ward] = []
	info[ward].append(name)

for ward in info.keys():
	print("+", ward)
	for name in info[ward]:
		print("| - ", name)

[vagrant@localhost python]$ python3 app.py
+ 磯子区
| – 滝頭小学校
| – 岡村小学校
| – 磯子小学校
| – 浜小学校
| – 杉田小学校
| – 根岸小学校
| – 屏風浦小学校
| – 梅林小学校
| – 汐見台小学校
| – 洋光台第一小学校
| – 洋光台第二小学校
| – さわの里小学校
| – 洋光台第三小学校
| – 洋光台第四小学校
| – 森東小学校
| – 山王台小学校

なるほど。xmlを作って公開したいですな。

<?php

$rootNode = new SimpleXMLElement("<rss xmlns:a10='http://www.w3.org/2005/Atom' version='2.0'><items></items>");

$itemNode = $rootNode->addChild('item');
$itemNode->addChild('title', '剰余金の配当に関するお知らせ');
$itemNode->addChild('description', '剰余金の配当を行うことを決議いたしました。');

$itemNode = $rootNode->addChild('item');
$itemNode->addChild('title', '監査役の異動に関するお知らせ');
$itemNode->addChild('description', '定時株主総会に付議する監査役の候補者につきまして、下記の通り内定いたしました。');

$itemNode = $rootNode->addChild('item');
$itemNode->addChild('title', '自己株式の取得状況に関するお知らせ');
$itemNode->addChild('description', '自己株式取得状況について、下記のとおりお知らせいたします。');

// $itemNode->addAttribute('stock', 'none');
$dom = new DOMDocument('1.0');
$dom->loadXML($rootNode->asXML());
$dom->formatOutput = true;
echo $dom->saveXML();

[Sat Aug 11 20:12:20 2018] 192.168.35.1:53532 [500]: /app.php – Uncaught exception ‘Exception’ with message ‘String could not be parsed as XML’ in /home/vagrant/python/app.php:3
Stack trace:
#0 /home/vagrant/python/app.php(3): SimpleXMLElement->__construct(‘


剰余金の配当に関するお知らせ
剰余金の配当を行うことを決議いたしました。


監査役の異動に関するお知らせ
定時株主総会に付議する監査役の候補者につきまして、下記の通り内定いたしました。


自己株式の取得状況に関するお知らせ
自己株式取得状況について、下記のとおりお知らせいたします。


[/php]

*.bin

バイナリーデータをつくる。
バイナリーデータ:コンピュータが処理・記憶するために2進化されたファイル

filename = "a.bin"
data = 100
with open(filename, "wb") as f:
	f.write(bytearray([data]))

[vagrant@localhost python]$ hexdump a.bin
0000000 0064
0000001

binary dataを見よう

binary data バイナリーファイルのデータを16進数や8進数で出力する

なんじゃこりゃー
[vagrant@localhost python]$ hexdump index.html
0000000 213c 4f44 5443 5059 2045 7468 6c6d 3c3e
0000010 7468 6c6d 6c20 6e61 3d67 6a22 2261 3c3e
0000020 6568 6461 3c3e 656d 6174 6320 6168 7372
0000030 7465 223d 7475 2d66 2238 3c3e 696c 6b6e
0000040 7220 6c65 223d 7473 6c79 7365 6568 7465
0000050 2022 7268 6665 223d 7363 2f73 7473 6c79
0000060 2e65 7363 2273 3c3e 6974 6c74 3e65 82e3
0000070 e3a2 a183 83e3 e380 b982 2f3c 6974 6c74
0000080 3e65 2f3c 6568 6461 3c3e 6f62 7964 3c3e
0000090 3168 e33e a282 83e3 e3a1 8083 82e3 e5b9
00000a0 a885 9be5 3cbd 682f 3e31 683c 3e72 733c
00000b0 6365 6974 6e6f 6920 3d64 7422 706f 3e22
00000c0 683c 3e32 99e9 e68d b4b0 87e9 3c8f 682f
00000d0 3e32 693c 676d 6320 616c 7373 223d 6d69
00000e0 6761 2265 7320 6372 223d 692f 616d 6567
00000f0 722f 6961 2e6e 6e70 2267 3c3e 732f 6365
0000100 6974 6e6f 3c3e 6573 7463 6f69 206e 6469
0000110 223d 6f74 2270 3c3e 3268 e63e 97b0 b8e6
0000120 3ca9 682f 3e32 693c 676d 6320 616c 7373
0000130 223d 6d69 6761 2265 7320 6372 223d 692f
0000140 616d 6567 742f 6d65 2e70 6e70 2267 3c3e
0000150 732f 6365 6974 6e6f 3c3e 6573 7463 6f69
0000160 206e 6469 223d 6f74 2270 3c3e 3268 e93e
0000170 a8a2 90e5 e391 bb83 a2e9 e9a8 9f80 2f3c
0000180 3268 3c3e 6d69 2067 6c63 7361 3d73 6922
0000190 616d 6567 2022 7273 3d63 2f22 6d69 6761
00001a0 2f65 6977 646e 702e 676e 3e22 2f3c 6573
00001b0 7463 6f69 3e6e 2f3c 6f62 7964 3c3e 682f
00001c0 6d74 3e6c
00001c4

そういえばマーケットスピードでtickerを複数画面で閲覧できるように編集する場合もバイナリーデータを編集しますよね。

為替データを取得して保存する

import urllib.request as request
import datetime
import json

API = "hoge"
json_str = request.urlopen(API).read().decode("utf-8")
data = json.loads(json_str)
print("1USD="+data["JPY"]+"JPY")

t = datetime.date.today()
fname = t.strftime("%Y-%m-%d") + ".json"
with open(fname, "w", encoding="utf-8") as f:
	f.write(json_str)

[vagrant@localhost python]$ python3 app.py
1USD=111.13473JPY

入ってますね。なるほど、datetime.date.today()か、datetime.strftime(datetime.now(),”%Y%m%d%H%M%S”)で時間を取得していましたが、日付だけならtodayで十分ですね。

コインチェックのデータを取りたい。
https://coincheck.com/ja/documents/exchange/api#about
https://coincheck.com/api/ticker

ん?
[vagrant@localhost python]$ python3 app.py
Traceback (most recent call last):
File “app.py”, line 8, in
print(“bid=”+data[“bid”]+”JPY, ask=”+data[“ask”])
TypeError: Can’t convert ‘float’ object to str implicitly

floatは駄目だと?書き直します。

print("bid="+str(data["bid"])+"JPY, ask="+str(data["ask"]))

なるほど。
[vagrant@localhost python]$ python3 app.py
bid=731751.0JPY, ask=732169.0

pythonでopenweathermapのAPIを叩こう

まず、jsonのapi request
http://api.openweathermap.org/data/2.5/weather?q=Tokyo,JP&APPID={apikey}

レスポンス

{"coord":{"lon":139.76,"lat":35.68},"weather":[{"id":701,"main":"Mist","description":"mist","icon":"50n"}],"base":"stations","main":{"temp":301.81,"pressure":1009,"humidity":66,"temp_min":301.15,"temp_max":302.15},"visibility":16093,"wind":{"speed":1.5,"deg":120},"clouds":{"all":1},"dt":1533250560,"sys":{"type":1,"id":7622,"message":0.0074,"country":"JP","sunrise":1533153003,"sunset":1533203030},"id":1850147,"name":"Tokyo","cod":200}

pythonで書きます。

import requests
import json

apikey = "hoge"

cities = ["Tokyo,JP", "London,UK", "New York, US"]
api = "http://api.openweathermap.org/data/2.5/weather?q={city}&APPID={key}"

k2c = lambda k: k - 273.15

for name in cities:
	url = api.format(city=name, key=apikey)
	r = requests.get(url)
	data = json.loads(r.text)
	print("+ 都市=", data["name"])
	print("| 天気=", data["weather"][0]["description"])
	print("| 最低気温=", k2c(data["main"]["temp_min"]))
	print("| 最高気温=", k2c(data["main"]["temp_max"]))
	print("| 湿度=", data["main"]["humidity"])
	print("| 気圧=", data["main"]["pressure"])
	print("| 風向き=", data["wind"]["deg"])
	print("| 風速度=", data["wind"]["speed"])
	print("")

コマンドライン
[vagrant@localhost python]$ python3 app.py
+ 都市= Tokyo
| 天気= mist
| 最低気温= 28.0
| 最高気温= 29.0
| 湿度= 66
| 気圧= 1009
| 風向き= 120
| 風速度= 1.5

+ 都市= London
| 天気= clear sky
| 最低気温= 20.0
| 最高気温= 24.0
| 湿度= 64
| 気圧= 1023
| 風向き= 230
| 風速度= 2.6

+ 都市= New York
| 天気= light rain
| 最低気温= 27.0
| 最高気温= 29.0
| 湿度= 69
| 気圧= 1019
Traceback (most recent call last):
File “app.py”, line 21, in
print(“| 風向き=”, data[“wind”][“deg”])
KeyError: ‘deg’

New Yorkの風向きがエラーになりますね。
new yorkのjsonを叩きます。
http://api.openweathermap.org/data/2.5/weather?q=New%20York,US&APPID={key}

{“coord”:{“lon”:-73.99,”lat”:40.73},”weather”:[{“id”:500,”main”:”Rain”,”description”:”light rain”,”icon”:”10d”}],”base”:”stations”,”main”:{“temp”:300.55,”pressure”:1019,”humidity”:69,”temp_min”:300.15,”temp_max”:302.15},”visibility”:16093,”wind”:{“speed”:2.6},”clouds”:{“all”:75},”dt”:1533250560,”sys”:{“type”:1,”id”:2121,”message”:0.0072,”country”:”US”,”sunrise”:1533203668,”sunset”:1533254951},”id”:5128581,”name”:”New York”,”cod”:200}

NewYorkのwindはspeedだけのようです。何故だ?wall streetは風向きなんて関係ないのかな。

execute_script()メソッド

from selenium import webdriver

browser = webdriver.PhantomJS()
browser.implicitly_wait(3)

browser.get("https://google.com")

r = browser.execute_script("return 100 + 50")
print(r)

[vagrant@localhost python]$ python3 app.py
/home/vagrant/.pyenv/versions/3.5.2/lib/python3.5/site-packages/selenium/webdriver/phantomjs/webdriver.py:49: UserWarning: Selenium support for PhantomJS has been deprecated, please use headless versions of Chrome or Firefox instead
warnings.warn(‘Selenium support for PhantomJS has been deprecated, please use headless ‘
150

r = browser.execute_script("var date = new Date(), console.log(date)")

windows10でIIS

コントロールパネル → プログラム → Windowsの機能の有効化または無効化 → インターネットインフォメーションサービス で有効にする。

seleniumをインストール

[vagrant@localhost python]$ pip3 install selenium
Collecting selenium
Downloading https://files.pythonhosted.org/packages/41/c6/78a9a0d0150dbf43095c6f422fdf6f948e18453c5ebbf92384175b372ca2/selenium-3.13.0-py2.py3-none-any.whl (946kB)
100% |████████████████████████████████| 952kB 552kB/s
Installing collected packages: selenium
Successfully installed selenium-3.13.0

R社にpythonからログイン

まさか、できるわけないよね。

import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin

USER = "hoge"
PASS = "hogehoge"

session = requests.session()

login_info = {
	"u" : USER,
	"p": PASS,
}
url_login = "https://grp01.id.rakuten.co.jp/rms/nid/vc?__event=login&service_id=top"
res = session.post(url_login, data=login_info)
res.raise_for_status()
print("success")

おい、ちょっと待て、ちょっと待て。マジこれ?これ、やばくないか。。。
[vagrant@localhost python]$ python3 app.py
success