Archive for the ‘Linux’ Category

今年の末にyahooブログがサービスを終了するにともなって、そのブログをwordpressに移行したいという依頼があった。
その中で、インポート用のテキストファイルから画像ファイルのリスト化をする処理の部分でawkを使ったところ、一行に2つ以上のimgタグとsrcが存在した場合、上手く要素を取得できないという問題に行き当たった。

こういう状態↓
dbf3ea701fd1719c9365a88c266f7709.png

私は最初、キャプチャーの位置を()でグルーピングして\1,\2などで取得するという方法しかわからなかった。
しかし、これでは当然、一行に3つ以上の要素がある場合マッチできない。

結局的に以下のコードでうまく行った。

awk 'BEGIN{FS="src=";}
{
	for(i=2;i<=NF;++i){
		if(match($i,/"[^"]*"/)){
			print substr($i,RSTART+1,RLENGTH-2);
		}
	}
}' ./source.txt

フィールドセパレーターを"src="に設定してあげることで、一行はimgタグのsrcで分割される。
iの初期値が2から始まっているのは、awkのカウントは0オリジンではなく、1オリジンであり、なおかつ"src="で区切られたフィールドの2つ目からマッチの試行を行いたいため。
あとは行中のマッチ位置のインデックスをRSTARTとRLENGTHで取得し、substr関数で切り抜く。

ウェブのフォーム入力テストの自動化をしたくて、Seleniumを導入しようとしたところ、下記のエラーが出て起動してくれない

環境:
Linux Ubuntu 18.04LTS
Python 3.7.3
pip 19.0.3
Google Chrome 75.0.3770.142
ChromeDriver 75.0.3770.140 (2d9f97485c7b07dc18a74666574f19176731995c-refs/branch-heads/3770@{#1155})

(unknown error: DevToolsActivePort file doesn't exist)
(The process started from chrome location /usr/bin/google-chrome is no longer running, so ChromeDriver is assuming that Chrome has crashed.)

結論としては環境変数$DISPLAYの設定が漏れていたからだった。

echo 'export DISPLAY="${DISPLAY:-:0}"' >> ~/.zshrc

にて解決。

だめな人は単にこれでも動くかも

export DISPLAY=:0.0

解決までの道筋

はじめに下記のURLを参考にSeleniumをインストールした
Python + Selenium で Chrome の自動操作を一通り - Qiita

しかし動かない…Firefoxの方も試してみたけど動かない。

次に下記のURLを参考にスクリーンショットを取得してみる

UbuntuのCLI環境でGoogleChromeを使ってウェブサイトのスクリーンショットを取得する - Qiita

たしかにGoogleの検索画面のスクリーンショットが取得できた。
chromedriverは動いていることを確認

ということは、ブラウザの起動まわりで上手く行っていないということが伺える。

そこでchromeを単体で実行(/usr/bin/google-chrome)してみる。
(google-chrome:29464): Gtk-WARNING **: 17:41:15.291: cannot open display:

というエラーが出て起動しないことで、DISPLAY周りで異常が起こっていることを突き止める。

最終的に下記URLを参考に.zshrcでDISPLAY環境変数を設定できていなかったことに気づく。
ubuntu で root 時に cannot open display となる件 - たつこの部屋


#google.py
import time
from selenium import webdriver

driver = webdriver.Chrome()
driver.get('https://www.google.com/')
time.sleep(5)
search_box = driver.find_element_by_name("q")
search_box.send_keys('ChromeDriver')
search_box.submit()
time.sleep(5)
driver.quit()

参考文献など :
$DISPLAYの設定: ubuntu で root 時に cannot open display となる件 - たつこの部屋
環境変数$DISPLAYについて: DISPLAY - なんなんなん行く?
seleniumのインストール: UbuntuのCLI環境でGoogleChromeを使ってウェブサイトのスクリーンショットを取得する - Qiita

1億2千万行のcsvデータをデータベースに保管したくなったので、rubyを使ってデータベース(Mysql)に挿入した。

gem install mysql

でrubyのmysqlライブラリを入れようとしたら

libmysqlclient-dev を先にaptでインストールするべしとのお告げを得たので

sudo apt install libmysqlclient-dev

でまずはlibmysqlclient-devをインストール

その後

gem install mysql

で無事gemが入った

以下mysqlDBにファイルからデータをINSERTするのに使ったコードです。

#!/usr/bin/ruby

require 'mysql'

client = Mysql::new("127.0.0.1", "username", "password", "db-name")

# set charcter code UTF-8
client.query("set character set utf8")

File.open('./source.csv', 'r') do |f|
    f.each_slice(1000) do |chunk|
        chunk.each do |lines|
			# chop() cuts "\n" end of line
            buf = lines.chop.split(',')
            client.query("INSERT INTO test(time,price,amount) VALUES(#{buf[0]},#{buf[1]},#{buf[2]});")
        end
    end
end

client.close

io.each_slice(1000)

普通のeachを使うと一行ずつの処理になってしまい、時間もかかるものと思われるが、each_slice(n)によってnの数分だけ一気に処理を行うことができる。

nの数は各々のメモリ搭載量に合わせて変更していただければと思います。

ただ想定外だったのは、これでも一万件のレコードを挿入するのにおよそ1分くらいかかってしまうこと

単純に計算して1億2千万件のレコードを挿入し終えるのは166時間以上の時間が必要ということになる…

NOSQLデータベースだったらもっと早いんだろうね。

そのうちそっち方面も探っていきたい