最近仕事とかプライベートが忙しく、完全に放置してました。
なお、楽しみにしてる人は・・・。
さて。今回のネタは insomnia と talend api tester
の二つです。
得意分野がそれぞれ違うので、私は使い分けしてます。
insomniaはスタンドアロンで動くけど、動的パラメータや戻りからの値を引き継いだりするのが難しい。
talend api testerはブラウザ依存(chrome)だけど、動的パラメータの扱いが強い。
具体的にキャプチャ貼ったりしてお見せするのが良いと思うのですが
如何せん仕事のデータなので貼れないのです・・・・・・申し訳ない。
今日はご紹介までに。
使い方が判らない方いたら言っていただければお教えしますよ!
最近はやりのVRChat APIなんかはinsomniaのほうがやりやすいです
]]>
色々調べてみると、DBの文字コードがutfからutfmb4に切り替わったことが原因のようで。
ネット見てると、
ROW_FORMAT=DYNAMIC
にしてあげると、直るってあったんですが、どこでDDL生成してるかが皆目さっぱりでした。
が、ついにみつけ、問題になっている箇所を特定できました。
]]> その場所とは/lib/MT/ObjectDriver/DDL.pm
の、
247 sub create_table_sql {
の数行下にある
$table_ddl .= ')'
の部分でした。
ここに、
$table_ddl .= ') ROW_FORMAT=DYNAMIC';
と指定してあげると、無事インストール完了。
みなさまのおやくにたてれば幸いです。
captch不要の時代が来るなんて誰が予想したでしょうか。
ロボット判別のためのチェックボックスはよく目にしますが、まだ新しい
チェックすら不要とというのはみたことありません。
読者の方で、見かけた人教えて下さい
まずこれはなんぞや。ってところから。
帳票出力したりするのに、PDFを出力することがよくありますよね。
そんなときに使えるミドルウェアの一つです。
ほかにも、mPDFとか、TCPDF とかがあります。
そんな中でも、頭一つ飛び抜けているのが、今回利用したwkhtmltopdfです。
HTMLからPDFを得ることが出来るのですが、HTMLの解釈部分にWebKitが使われており
CSS3やHTML5等ももそのままの形で出力できます。
で。帳票というと、Header, Footer(見出しとページ数とか)がつきものですよね。。
Debianを利用している環境であれば
# apt-get install wkhtmltopdf
でインストールし
$ wkhtmltopdf http://www.yahoo.co.jp yahoo.pdf
といった感じで、pdf出力ができます。
----------- ここから先は、header, footerを利用する人のみ必要な箇所です。 ---------------------
上記のバージョンではQTのパッチがあたっていないためheader, footerを指定することが出来ません。
なので、もしインストールしている人は
# apt-get purge wkhtmltopdf
するか、インストールしっぱなしでもいいので、公式サイトからパッケージをダウンロードして展開する必要があります。
公式サイトから、最新(2016/07/08時点では、0.12.3.2 が最新でした。
で、このファイル、よく見るとxz という拡張子がついており、tar.gzのように、tar xzvf では解凍できません。
tar Jxvf wkhtmltox-0.12.3_linux-generic-amd64.tar.xz
で、解凍します(tarのバージョンによります。詳しくはググってください)
また、上記はx64です。i386の場合は、素直にx86バージョンをダウンロードして下さい。
解凍したフォルダを、/usr/local/wkhtmltopdf 等にコピー(移動でもかまいませんよ?)して・・・
いよいよ、本番のheader, footerを入れる作業に入ります。
<!DOCTYPE html>
<body>
<div style="display: inline-block; text-align:left; width: 48%;">
<span id="current_date"></span>
</div>
<div style="display: inline-block; text-align:right; width: 48%;">
Page <span style="display: inline-block;" id="current_page"></span> of <span style="display: inline-block;" id="page_count"></span>
</div>
<script type="text/javascript">
var pdfInfo = {};
var x = document.location.search.substring(1).split('&');
for (var i in x) { var z = x[i].split('=',2); pdfInfo[z[0]] = unescape(z[1]); }
function getPdfInfo() {
var page = pdfInfo.page || 1;
var pageCount = pdfInfo.topage || 1;
var date = pdfInfo.date || 1;
document.getElementById('current_page').textContent = page;
document.getElementById('page_count').textContent = pageCount;
document.getElementById('current_date').textContent = date;
}
getPdfInfo();
</script>
</body>
</html>
次に、headerに入れるhtmlを準備します。名前は、header.htmlとします。
こちらは、適当でかまいません。タイトルとか。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
Yahoo to PDF
</body>
</html>
準備が整ったら、wkhtmlでpdfの生成を行います。
$ wkhtml --header-html header.html --footer-html footer.html http://www.yahoo.co.jp yahoo.pdf
上記で、ヘッダーとフッター、ページ数付きのpdfが出力されます。
どなたかのお役にたてれば幸いです。
]]>というわけで、PythonでChromeDriverを使って、キャプチャ取得する方法をまとめます。
PC/Mobileを引数で指定して、Mobileの場合はChromeのモバイルエミュレートで
取得する事にしました。
JavaでもChromeDriver使えるのですが、「すっごく重い」「メモリ食いまくり」でした。
代替案として出てきたのがPythonです。
以下、実際のコードを交えながら説明していきます。
まず。前提として、サーバーに導入されていないであろう、chromedriverはインストールしておいてください。
chromedriverは、apt-get, yum にて導入可能なはずです。
インストールできない場合は、こちら より、ダウンロードして任意のパスへ導入してください。
また、普通にpythonを使っているだけだと、python用のselenium, xvfbwrapperも入ってないはずなので
pip install selenium
pip install xvfbwrapper
をコンソールで実行し、インストールしてください(rootに準ずる権限が必要です)
]]> # -*- coding: utf-8 -*- import sys, time, glob, ConfigParser from selenium.common.exceptions import WebDriverException from selenium import webdriver from selenium.webdriver.chrome.options import Options from xvfbwrapper import Xvfb if __name__ == "__main__": param = sys.argv if len(param) != 4: print "Usage: cap.py
さて。上記コードですが、重要な部分のみ取り上げ、解説します。
まずは
ini.read('cap.py.ini')
このコードで、設定を読み込んでいます。
設定内容は次の通りです。
[capture]
chromedriver = /usr/lib/chromium/chromedriver
useragent.pc = Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.10 Safari/537.36
windowsize.pc = 1920,1080
useragent.mobile = Mozilla/5.0 (iPhone; CPU iPhone OS 8_4 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) CriOS/46.0.2490.85 Mobile/12H143 Safari/600.1.4
windowsize.mobile = 375,667
chromedriverの場所、PCとMobileのUAと画面サイズの設定ですね。
chrome_options = Options()
chrome_options.add_argument("--no-sandbox")
chromeの各種設定です。
設定内容にについては、https://sites.google.com/a/chromium.org/chromedriver/capabilities
に一通り載っていますので、割愛させていただきます。
次が非常に大事ですね。DeviceをMobileとして指定したときに、chromeのmobile emulateを行っています。
if device == "Mobile":
window_size_list = displaySize.split(",")
mobile_emulation = {"deviceMetrics": { "width": int(window_size_list[0]), "height": int(window_size_list[1]), "pixelRatio": 3.0 }}
chrome_options.add_experimental_option("mobileEmulation", mobile_emulation)
次に、driverのインスタンスを作成して、drver.get()でアクセスしています。
このコードが一発でわかる人はいないのではないか。というのが次のコードです。
try:
alert = driver.switch_to_alert()
alert.accept()
except:
print "no alert to accept"
これは、モバイルへ誘導されるときにjsのalertがあがるサイトへの対策です。
アラートが存在すれば、、OKをエミュレートしています。
time.sleep(10)
try:
driver.save_screenshot(cappath)
except
上記では、10秒スリープさせてますが、これは、ページの描画待ち処理です。
time.sleep(10)をなくして実行してみると、例えばjsでの遅延ロードなどがロードされないまま
キャプチャされてしまいます。
最後に、driver.quit() 及び vdi.stoip() でドライバの停止と仮想ディスプレイの停止を行って
処理終了です。
大まかな部分のみ説明しましたが、お役に立てれば何よりです。
chromedriverの説明は国内の情報は少なめなので。
今回は、マルチスレッドを簡単に実装する方法についてちょっとまとめてみました。
よろしければお付き合いください。
]]> まず、マルチスレッドとマルチプロセスにつじてですがどちらをとるかは好みの問題ですが。今回は、マルチスレッドについて書いていきます。
まずは、サンプルコードをご覧ください。
# -*- coding: utf-8 -*- import threading def thread_test(tname, maxval): localval = 0 while True: localval += 1 print "[" + tname + "] localval : " + str(localval) if (localval == maxval): break; return if __name__ == "__main__": t1 = threading.Thread(target=thread_test, name="thread1", args=("thread1", 1000)) t2 = threading.Thread(target=thread_test, name="thread2", args=("thread2", 2000)) t3 = threading.Thread(target=thread_test, name="thread3", args=("thread3", 3000)) t1.start() t2.start() t3.start()
と、たったこれだけで、マルチスレッドで動きます。
(実際に動くコードですので、環境をお持ちの方は試してみてください)
肝になるのは、
import threading
threading.Thread(...)
の部分です。
import文で、threading の関数の読み込みと
threading.Thread で、スレッドの実物作成ですね。
作成した後は、start()するだけです。
JavaやC#、Perlを触ったことある人なら、感覚で書ける感じがたまりません。
(すみません。Rubyは勉強不足です・・・・)
マルチプロセスについては、また別途取り上げようと思います。
]]>体調面等の調整で、数か月空いてしまいました。
また、技術系の記事をまとめていきたいと思いますので、今後ともよろしくお願いします。
さて。今日の本題。
777TOWNを遊ぼうとして、「ファイルの更新に失敗しました」のエラーが発生する場合に
有効な対処が見つかりましたので、書き残しておきます。
※公式で報告されている方法ではありません
※PC(特にネットワーク回り)への知識が必要です。(ということにしておきます)
以下の方法は、私の環境依存の可能性もありますので、必ず解決するとは限りません。
環境は
・OS: Windows10 x64
すると、あら不思議。アップデートが正常にできるじゃありませんか。
おそらくですが、cache.777town.net のNSが負荷に耐えられないのでは。と考えられます。
なお、本対策を行ったのちアップデートが正常に終了すると、boot.iniが編集前の状態に戻ることを確認済みです。
起動できない場合に毎回行う必要がある。ということです。
Program Files以下に配置されている関係で、batやexe等では簡単には書き換えができないので
手動にて対応してみてください。
また、上記で正常にアップデートが終了するようになった方、いましたら、本記事へコメントを残していただけますと幸いです。
]]>ぼちぼち更新しますので、宜しくお願いします。
]]>jqueryのbeforeSendを使うことで、送信前にリクエストヘッダの書き換えを行い X-Requested-Withの値を空にすることで、Ajaxリクエストと認識させない
]]>Googleで検索すると、オートテストや、スクリーンキャプチャなどに用いられています。
オートテストの項目の中で、「ページの表示速度をチェックする。」という事があると思います。
このとき、PhantomJSのexamplesについてくる、「loadspeed.js」がほぼそのまま利用できるのですが
ランダムなUserAgentでのテストを要求されるパターンもあるかと思います。
ここでは、PhantomJSに対し、ランダムなUserAgentを設定する方法を紹介します。
]]> PhantomJSで、UserAgentを設定するにはこの値をいかにしてランダムにするか。ですが、流用可能な形にしたかったので
PhantomJSのfs.read()を使って外部からUAの一覧を読み込み、Math.random()を使って、配列からランダムに取得することにしました。
まず、以下のようなテキストファイルを準備します。
[
'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2560.0 Safari/537.36',
'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; rv:11.0) like Gecko',
'Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240',
... 以下、必要な分だけ記述
]
JavaScriptの配列ですね。これを、任意の場所に配置します。
今回は、/opt/pjs/ua.txtとして保存します。
次に、PhantomJSのスクリプトです。
var ua = fs.read('/opt/pjs/ua.txt');
ua = eval(ua);
var useragent = ua[Math.floor(Math.random() * ua.length)];
はい。以上で、useragentをランダムに取得することができました。これを、
page.settings.userAgent = useragent;
として設定すれば完了です。
以上の記述量であれば、他のスクリプト(たとえば、スクリーンキャプチャ)等にも
流用しやすいと思います。
是非使ってみてください!
]]>にて、唐揚げを食べてきました。
10個で900円。
噂によると、かなり大きいとか。
食べきれるでしょうか。
8個食べきれば勝ち(2個は同行者が食べました)。という勝負にのってやってきました。
そして、やってきました。唐揚げ10個!
]]>みてください。このボリューム。
10個でこれです。
手前のレモンが飾りにしかなっていないという。
タバコの高さほどあります。
一つ一つが、タバコの箱よりも大きい!
揚げたてで、味は非常によかったです。一緒に頼んだポテトサラダと一緒に食べるとこれまた良いアクセントに。
5個ほど食べたあたりで、かなりの脂っこさが唇の周りに。
ですが!
8個完食しました!(完食した皿の画像は取り損ねました)
御茶の水に用事がある方は、是非1度は見ておくと良いかと。
ただし、10個頼む場合は3~4人で食べるのが正解でしょうw
]]>XHProf
XH GUI
CallGraph(Graphviz)
のプロファイル環境を構築しました。
以下、インストール時のメモです。
]]> 1. xhprofのインストール# pecl install xhprof-0.9.4
xhprofを読み込むため、xhprof.iniの作成とシンボリックリンクの作成を行います。
# vi /etc/php5/mods-available/xhprof.ini
ファイルの中身は以下の1行のみです。
extension=xhprof.so
xhprof.iniを有効にするため、以下の作業を行います。
# cd /etc/php5/fpm/conf.d
# ln -s ../../mods-available/xhprof.ini 30-xhprof.ini
# systemctl restart php5-fpm
2. XH GUIのダウンロードと配置
XH GUIはgitにて公開されています。gitコマンドを使ってcloneします。
cloneしたファイル一式を/opt/xhprof として配置します。
# cd /usr/local/src
# git clone https://github.com/preinheimer/xhprof.git
# mv xhprof /opt/xhprof
3. Graphvizのインストール
これは、debパッケージが普通に提供されているため、apt-getでインストールします。
# apt-get install graphviz
4. XH GUIとCallGraphの設定準備 XH GUIの設定ファイルを準備します。
# cd /opt/xhprof/xhprof_lib
# cp config.sample.php config.php
バックエンドにMySQLを利用。及び、Graphvizの設定を行います。
MySQLへの接続は、mysqliを利用します。
今回は、DBサーバーが別サーバーのため、mysqlサーバーへユーザーの追加も行います。
# ssh db1
*db1は、任意のサーバーを選択してください。
ローカルのmysqlを利用するときは、この行を無視してください。
# mysql -uroot -p****
mysql> create database xhprof;
mysql> grant all on xhprof.* to xhprof@'192.168.0.0/255.255.255.0' identified by 'xhprof';
mysql> flush privileges;
mysql> quit
# exit
青色の箇所は、お使いの環境によって変更してください。
たとえば、MySQLがローカルで動いていれば、localhost ですね。
5. XH GUI用のSQLを流し込み XH GUIに、MySQL用のcreate table文が入っているため、これを利用します。
# cd /opt/xhprof/xhprof_lib/utils/Db
# cat Mysqli.php
※ファイルの先頭にcreate table文がはいっているので、コピーしておく
# ssh db1
# mysql -xhprof -pxhprof -A xhprof -h 192.168.0.10
mysql> ... ここにcreate table文を貼り付け
mysql> exit
# exit
6. XH GUIの設定ファイル編集
# cd /opt/xhprof/xhprof_lib/
# vi config.php
以下では、実際に行った設定内容を記述します。(一部伏せてます)
・5 行目付近 sec.5で行ったDB設定を反映
$_xhprof['dbtype'] = 'mysql'; // Only relevant for PDO
$_xhprof['dbhost'] = '192.168.0.10';
$_xhprof['dbuser'] = 'xhprof';
$_xhprof['dbpass'] = 'xhprof';
$_xhprof['dbname'] = 'xhprof';
$_xhprof['dbadapter'] = 'Mysqli';
$_xhprof['servername'] = 'myserver';
$_xhprof['namespace'] = 'myapp';
$_xhprof['url'] = 'http://xhprof.example.com'; // <- nginxで設定するURLを指定。 sec.7を参照
・31行目付近(コメントアウトを外す)
$_xhprof['dot_binary'] = '/usr/bin/dot';
$_xhprof['dot_tempdir'] = '/tmp';
$_xhprof['dot_errfile'] = '/tmp/xh_dot.err';
・52行目付近 アクセスコントロールを無効にする
$controlIPs = false; //Disables access controlls completely.
// $controlIPs = array();
// $controlIPs[] = "127.0.0.1"; // localhost, you'll want to add your own ip here
// $controlIPs[] = "::1"; // localhost IP v6
7. XH GUIの公開
以下はnginxの設定例です。
# cd /etc/nginx/conf.v/
# vi xhprof.example.com.conf
server {
listen 80;
server_name xhprof.example.com;
root /opt/xhprof/xhprof_html/;
index index.php index.html index.htm;
charset utf-8;
location = /robots.txt { access_log off; log_not_found off; }
location = /favicon.ico { access_log off; log_not_found off; }
location ~* \.php$ {
expires off;
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
}
8. xhprofを有効にする
xhprofを有効にするドメインのfcgiパラメータを編集します。
# vi dev.example.com.conf
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
...
fastcgi_param PHP_VALUE
"auto_prepend_file=/opt/xhprof/external/header.php \n
auto_append_file=/opt/xhprof/external/footer.php"; // 以上3行を追加する
}
9. nginxの設定確認
# /etc/init.d/nginx configtest
10. nginx再起動
# systemctl restart nginx
11. sec.8で有効にしたドメインへ、特殊パラメータをつけてアクセス
http://dev.example.com/?_profile=1
一度profile=1をつけると、cookieにprofileのフラグが立つため、無効にする場合は
http://dev.example.coim/?_profile=0
とアクセスする。
12. xhprof及びXH GUI, Graphvizが動作していることを確認
http://xhprof.example.com/ へアクセスし、XH GUIが動作していることを確認
]]>新年1発目のネタは、Let's Encryptという、SSLの証明機関のオープンソース版みたいなものを
試してみました。
残念ながら、このblogが動いているサーバーでは動作しなかったので(Debian stretch)
VM上に、Debian Jessieをインストールして検証しました。
ちなみに、Debian stretchで動かない原因は「gccのバグ」です。
早めに修正されて、deb展開されることを祈っています
(海外フォーラムで見る限りだと、すでにbackportsされているようなのですが。)
VMへ新規インストールしたため、apacheも入っていない状態からスタートします。
1. git, apache2のインストール
apt-get install apache2 git
2. 80, 443ポートを開放
設定するドメインを本当に所持しているか確認しにきます。
ufwやiptables等で弾いている場合は解放しましょう。
自宅サーバーの場合は、ルーターでポートマップしておきましょう。
3. letsencryptをgitからclone
任意のディレクトリで、以下のコマンドを実行します。
# git clone https://github.com/letsencrypt/letsencrypt
4. letsencrypt-auto を単体で実行し、必要なパッケージのインストール
# cd letsencrypt
# ./letsencrypt-auto
5. 証明書の取得、作成、設定
# ./letsencrypt-auto certonly --apache -d <所有ドメイン>
6. Apacheの設定が勝手に書き換わり、443の定義が二つ現れるため片方コメントアウト
# cd /etc/apache2/
# vi ports.conf
<IfModule ssl_module>
Listen 443
</IfModule>
と、
<IfModule mod_ssl.c>
Listen *:443
</IfModule>
の二つが設定されているはずなので、元々ある上の設定をコメントアウト
7. Apache2の起動 # systemctl start apache2.service
8. SSLlabs等を利用し、SSLの設定が正常に行われているか確認
https://www.ssllabs.com/ssltest/analyze.html?d=<所有ドメイン>
以上です。非常に簡単。便利。
standaloneで取得して設定する必要のほうが多いとは思いますがそれを差し置いても、外部に委託して証明書を作成するよりははるかに楽です。
さぁ、あなたも let's try!
]]>in_array(strtolower($needle), array_map('strtolower', $haystack));]]>
$needleで、$haystackを検索する。
array_mapにより、haystackの中身を全て小文字に変換し、strtolowerで検索する文字列も小文字にする。
このため、大文字小文字を区別しない検索ができる。
以下では4項目のみ取り上げますが、もっと盛りだくさんの機能追加がされています。
1. "??"(null比較演算子)
与えられた左辺がnullの場合、右辺で定義した値を返す
たとえば、下記のような書き方をします。
$arr1['abc'] = 'def'; return $arr1['abc'] ?? false; // ptn1: $arr1['abc']は定義されているので、'def'が返る return $arr2['abc'] ?? false; // ptn2: $arr2['abc']は定義されていないため、falseが返る
ptn2の場合は、isnullやissetを利用して通常確認するため
isnull、isset地獄から抜け出せる可能性大ですね。
2. "<=>"(組み合わせ比較演算子)
左辺が大きい場合に1、右辺が大きい場合に-1を返す)
例:
return 1 <=> 2 // -1 return 2 <=> 1 // 1
威力を発揮するのは、usort等でしょうか。
たとえばこんな感じの。
usort($array, function($a, $b) { return $a <=> $b; });]]> 3. 戻り型の指定(Return Types)
function getArrData() : array { return 10; } $retArr = getArrData();
上記コードでは、getArrDataはarrayを返すようになっているのに、intを返しているため
PHP Fatal error: Uncaught TypeError: Return value of getArrData() must be of the type array, integer returned
というエラーが発生します。
4. Exception on Fatals
これまでFatal Errorが発生すると止まっていたコードをtry~catchでかこむことで
Exceptionを発生させ、コードの実行中断をなくすことができます。
try { $ret = method(); print $ret; }catch(EngineException $ee) { print "Caught Exception: " . $ee->getMessage(); }
method()は定義されていないため、通常はFatalErrorで実行停止しますが
上記の場合は、メッセージを出力しながら続きを実行することが出来ます。