作成中
投稿者: Hisa
Python 基本メモ ループでzipを使う
最近になって、Pythonを始めてみました。
Javaで行っていたWEBページのスクレープをPythonに移行中です。
今更ながらと言われるかも知れませんが、Javaに比べてコードが大きく減らせて、大幅生産性向上が出来て驚いてます。
そんな中で、リスト内包表記と同じく便利なので使ってるzip関数による複数変数ループを備忘録しておきます。
< コード例 >
## ++ 店名 住所 電話番号 走査 ++ ##
for nm, addr, tel in zip(namelist, addrlist, tellist):
# 経緯度、郵便番号ジオコーダー #
if addr is not None and addr != "":
geo = g.Google(addr)
llz = geo.getLatLonZip()
dict = {"gp": GP,"list": LIST_NAME, "name": nm, "addr": addr, "tel": tel,
"lat": llz["lat"], "lon": llz["lon"], "zip": llz["zip"], "icon": ICON_NAME}
print(dict)
dictlist.append(dict)
return dictlist
Leaflet Javascript ツールチップがポリラインに重ならないようにする
< コード例 >
/**
* チャートWaypointツールチップ位置、オフセット取得
* 三角形にして頂点(カレント)への方向の領域を返す
*
* @param {type} prev 前回データ
* @param {type} curr 今回データ
* @param {type} next 次回データ
* @returns {StaticMap.getTooltipDirection.staticmapAnonym$9} Direction文字列、
* オフセットxy配列
*/
getTooltipDirectionByArrow(prev, curr, next) {
const DIRECTIONS = ["top", "right", "bottom", "left"]
const OFFSETS = [[0, -10], [10, 0], [[0, 10]], [-10, 0]]
const pll = [prev["LON"], prev["LAT"]]
const cll = [curr["LON"], curr["LAT"]]
const nll = [next["LON"], next["LAT"]]
const tf = new MyTurf()
let topdir = parseInt(tf.getBearing(cll, pll) + 45)
let tondir = parseInt(tf.getBearing(cll, nll) + 45)
topdir = topdir < 0 ? topdir + 360 : topdir
tondir = tondir < 0 ? tondir + 360 : tondir
const diffdir = Math.abs(topdir - tondir)
// p -> c -> n が直線になってない場合 //
if (diffdir > 190 && diffdir < 170) {
// PとNの中間点 //
const pnc = tf.midpoint(pll, nll)
// PN中間点からのCへの方向 //
let arrowdir = parseInt(tf.getBearing(pnc, cll) + 45)
arrowdir = arrowdir < 0 ? arrowdir + 360 : arrowdir
const arrowArea = Math.floor(arrowdir / 90)
return {
direction: DIRECTIONS[arrowArea],
offset: OFFSETS[arrowArea]
}
}
// 直線になってる場合、線なし領域最初を返す //
else {
return new StaticMap().getTooltipDirection(prev, curr, next)
}
}
/**
* チャートWaypointツールチップ位置、オフセット取得
* 線が引かれてない領域を返す
*
* @param {type} prev 前回データ
* @param {type} curr 今回データ
* @param {type} next 次回データ
* @returns {StaticMap.getTooltipDirection.staticmapAnonym$9} Direction文字列、
* オフセットxy配列
*/
getTooltipDirection(prev, curr, next) {
const AREAS = [0, 1, 2, 3]
const DIRECTIONS = ["top", "right", "bottom", "left"]
const OFFSETS = [[0, -10], [10, 0], [[0, 10]], [-10, 0]]
const pll = [prev["LON"], prev["LAT"]]
const cll = [curr["LON"], curr["LAT"]]
const nll = [next["LON"], next["LAT"]]
const tf = new MyTurf()
let topdir = parseInt(tf.getBearing(cll, pll) + 45)
let tondir = parseInt(tf.getBearing(cll, nll) + 45)
topdir = topdir < 0 ? topdir + 360 : topdir
tondir = tondir < 0 ? tondir + 360 : tondir
const pavoidArea = Math.floor(topdir / 90)
const navoidArea = Math.floor(tondir / 90)
// 余った領域 //
const putAreas = AREAS.filter(n => n !== pavoidArea && n !== navoidArea)
return {
//topdir: topdir,
//tondir: tondir,
//pavoidArea: pavoidArea,
//navoidArea: navoidArea,
//putAreas: putAreas,
direction: DIRECTIONS[putAreas[0]],
offset: OFFSETS[putAreas[0]]
}
}
Call
const tff = new StaticMap()
pdatas.forEach((p, i) => {
plls.push([p["LAT"], p["LON"]])
if (i > 0 && i < pdatas.length - 1) {
//console.log("-- offset result " + p["IDENT"])
// ツールチップ配置位置、オフセット //
const ttpdir = tff.getTooltipDirectionByArrow(pdatas[i - 1], p, pdatas[i + 1])
//console.log(ttpdir)
ttpdirs.push(ttpdir["direction"])
ttpoffsets.push(ttpdir["offset"])
}
})
< 画面例 >
|
Leaflet Javascript arrowheadプラグインで矢印をつける
飛行機の飛行経路チャートで方向がわかるようにするため矢印をつけるプラグインを探してたところ、ぴったりなのが見つかり早速使ってみました。
< コード例 >
HTML
<!-- Leaflet aroowhead --> <script src="Script/js/leaflet-arrowheads.js"></script> <script src="Script/js/leaflet.geometryutil.js"></script>
Javascript
const ARROWHEADS_OPTIONS = { size: '12px', yawn: 50, fill: true, //frequency: 'endonly', frequency: '20000m', offsets: {end: '12px'} } this.lines = L.polyline(plls, POLYLINE_OPTIONS).arrowheads(ARROWHEADS_OPTIONS).addTo(this.smap)
< 画面例 >
|
Python 時刻形式経緯度十進変換関数クラス
航空や気象で扱われてる時刻形式の経緯度を地図で扱うために、十進値に変換する関数を作ってクラスにしてみました。
< コード例 >
クラス
'''
時刻形式経緯度十進変換クラス
'''
class DigitLL:
'''
コンストラクタ
txt : 時刻経緯度
endchr : N or S or E or W
'''
def __init__(self, txt, endchr):
self.txt = txt
self.endchr = endchr
'''
十進変換
'''
def digitLLFromTimeLL(self):
numInt = int(self.txt)
# 整数部
hourPartVal = int(numInt / 10000)
# 分
minutePartVal = int(numInt / 100) % 100
# 秒
secondPartVal = numInt % 100
minuteVal = minutePartVal / 60
secondVal = secondPartVal / 3600
resval = hourPartVal + minuteVal + secondVa
# 南半球、西半球の場合 #
if (self.endchr == "S" or self.endchr == "W
resval = resval * -1
# debug
# print(str(hourPartVal) + ":" + str(minute
return resval
呼び出し
ダウンロードしたExcelのファイルのセルの値を読み込んで変換する場面で使ってます。
'''
Waypointエクセルファイル読込
使用
wp_euro_procedure.pyから使う
filename : エクセルファイル名
effdate_end : effective expired date
'''
def readExcel(filename, effdate_end):
wb = openpyxl.load_workbook(filename)
sheet = wb["FRA Points"]
# 書き込み用タプルリスト追加 #
tpllist = []
# 行数を調べる #
rowmax = getDataRowMax(sheet)
# identcol = "C" + str(i + 2)
## ++ 辞書値リスト追加走査 ++ ##
for i in range(rowmax):
ident = sheet["C" + str(i + 2)].value
type = sheet["A" + str(i + 2)].value
latcval = sheet["D" + str(i + 2)].value
loncval = sheet["E" + str(i + 2)].value
name = sheet["F" + str(i + 2)].value
#if type == None:
# type = "FIX"
type = "FIX" if type == None else type
latendchr = latcval[0:1]
lonendchr = loncval[0:1]
latvalpart = latcval[1:]
lonvalpart = loncval[1:]
#lat = digitLLFromTimeLL(latvalpart, latendchr)
#lon = digitLLFromTimeLL(lonvalpart, lonendchr)
# クラスを使う #
dll_lat = dll.DigitLL(latvalpart, latendchr)
dll_lon = dll.DigitLL(lonvalpart, lonendchr)
lat = dll_lat.digitLLFromTimeLL()
lon = dll_lon.digitLLFromTimeLL()
# debug
print(ident)
print(latcval + " => " + str(lat))
print(loncval + " => " + str(lon))
print("-------------------------------------------")
tpl = {"type": "", "ident": "", "name": "", "lat": -500, "lon": -500}
if lat != 0 and lon != 0:
tpl["type"] = type
tpl["ident"] = ident
tpl["name"] = name
tpl["lat"] = lat
tpl["lon"] = lon
tpllist.append(tpl)
< エクセルファイル例 >
|
Javascript 時刻形式経緯度十進変換関数
気象や航空関係のデータの経緯度の形式が時刻なものを、Leafletの地図で扱う場合のデータ検証用として、
地名入力してジオコーダーを使って移動させるような処理を、入力値を時刻経緯度で行うために作ってみました。
< コード例 >
/**
* 時刻経緯度十進変換
*
* @param txt 入力文字列 ex. 353220.86N
* 1394906.93E
*/
const getDecLocationFromTimeLocation = (txt) => {
let res = ""
const pos_comma = txt.indexOf(".")
const txt_int_part = txt.slice(0, pos_comma)
let txt_dec_part = txt.slice(pos_comma + 1)
txt_dec_part = txt_dec_part.replace("N", "").replace("S", "").replace("W", "").replace("E", "")
let txt_int = ""
let txt_min = ""
//alert(txt_int_part + "\n" + txt_int_part.length)
// 整数部分、分の切り取り //
switch (txt_int_part.length) {
// 整数1桁 //
case 5:
txt_int = txt_int_part.slice(0, 1)
txt_min = txt_int_part.slice(1, 3)
break
// 整数2桁 //
case 6:
txt_int = txt_int_part.slice(0, 2)
txt_min = txt_int_part.slice(2, 4)
break;
// 整数3桁 //
case 7:
txt_int = txt_int_part.slice(0, 3)
txt_min = txt_int_part.slice(3, 5)
break
}
// 秒は常に右2文字
const txt_sec = txt_int_part.slice(-2)
//alert (txt_int + ":" + txt_min + ":" + txt_sec + "." + txt_dec_part)
res = Number(txt_int) +
Number(txt_min / 60) +
Number(txt_sec / 3600) +
Number(txt_dec_part / 360000)
// 南半球の場合 //
if (txt.slice(-1) === "S" || txt.slice(-1) === "W") {
res = res * -1
}
return res
}
作ってから気づいたのですが、整数部分の分秒の変換は、Pythonでの例ですが、
numInt = int(self.txt)
# 整数部
hourPartVal = int(numInt / 10000)
# 分
minutePartVal = int(numInt / 100) % 100
# 秒
secondPartVal = numInt % 100
minuteVal = minutePartVal / 60
secondVal = secondPartVal / 3600
resval = hourPartVal + minuteVal + secondVal
のようにすれば簡潔になります。
< 利用例 >
AiP JAPANに載っている FIXのWaypoint EPSON がどこにあるか調べる
千葉県にあることがわかる
MySQL 時刻形式経緯度十進変換関数
ページスクレープしたテキストをデータベースに登録する為、seleniumやsoupを使えば、とったテキストが整ってる場合は、自分のプログラムに関数を入れ処理出来ますが、コピペしてエクセルに貼り付けてSQLにしないと出来ないような整理されてないソースだったので、MySQLのUDFで作ってみました。
CREATE DEFINER=`root`@`localhost` FUNCTION `fc_decLL_from_timeLL`( `srctxt` VARCHAR(20) ) RETURNS double LANGUAGE SQL NOT DETERMINISTIC CONTAINS SQL SQL SECURITY DEFINER COMMENT '時刻経緯度十進変換関数' BEGIN DECLARE resLL DOUBLE DEFAULT 0; -- decimaled return value DECLARE pos_comma TINYINT; -- chart index of . DECLARE txt_int_part VARCHAR(7); -- always 7char or 6char DECLARE txt_dec_part VARCHAR(2); -- decimal part text DECLARE chr_nesw CHAR(1); -- north or east or south or west DECLARE txt_int VARCHAR(3); -- 2 char or 3 char DECLARE txt_min CHAR(2); -- always 2 char DECLARE txt_sec CHAR(2); -- always 2 char SET pos_comma = INSTR(srctxt, '.'); SET txt_int_part = LEFT(srctxt, pos_comma - 1); SET txt_dec_part = SUBSTR(srctxt, pos_comma + 1, pos_comma + 4); SET txt_dec_part = TRIM('N' FROM txt_dec_part); SET txt_dec_part = TRIM('S' FROM txt_dec_part); SET txt_dec_part = TRIM('W' FROM txt_dec_part); SET txt_dec_part = TRIM('E' FROM txt_dec_part); -- 整数部分、分の切り取り IF LENGTH(txt_int_part) = 5 THEN SET txt_int = LEFT(txt_int_part, 1); SET txt_min = MID(txt_int_part, 2, 2); ELSEIF LENGTH(txt_int_part) = 6 THEN SET txt_int = LEFT(txt_int_part, 2); SET txt_min = MID(txt_int_part, 3, 2); ELSEIF LENGTH(txt_int_part) = 7 THEN SET txt_int = LEFT(txt_int_part, 3); SET txt_min = MID(txt_int_part, 4, 2); END IF; -- 秒は常に右2文字 SET txt_sec = RIGHT(txt_int_part, 2); SET chr_nesw = RIGHT(srctxt, 1); SET resLL = CAST(txt_int AS UNSIGNED) + CAST(txt_min AS UNSIGNED) / 60 + CAST(txt_sec AS UNSIGNED) / 3600 + CAST(txt_dec_part AS UNSIGNED) / 360000; -- 南半球、西半球の場合 IF (chr_nesw = 'S' OR chr_nesw = 'W') THEN SET resLL = resLL * -1; END IF; -- debug -- INSERT INTO tst (fld0, fld1) VALUES(txt_int_part, txt_dec_part); -- INSERT INTO tst (fld0, fld1, fld2) VALUES(txt_int, txt_min, txt_sec); RETURN resLL; END
< テキストソース例 >
< Excel貼付例 >
坂本龍一・遊び創作
遊びは結果を求めませんし、プロセス。僕が音楽を作るのもそんなプロセスが面白いから。子供の砂遊びみたいに、何を作ろうとイメージするのではなく、いじっているうちに形になっていく。それが創作であり、僕にとって創作こそ遊びだと思います。
Python tqdmでプログレス表示
ここで教えて頂きました。
< コード例 >
pos = 0
for icao in tqdm(ICAOS):
url = BASE_URL.replace("##ICAO##", icao[0])
driver.get(url)
time.sleep(5)
pos += 1
if pos <= 4:
continue
< 画面例 >
62%|███████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 184/299 [38:59<23:30, 12.26s/it]E55P:64257 {}
コメントを投稿するにはログインしてください。