メルカリ出品のブラウザ上操作を自動化する その1

こんにちは、シュンです。

最近メルカリをヘビーユースしています。
でもブラウザ上でのマウス操作が大嫌いなんです。
というわけで自動化システムの開発をはじめました。

ブラウザ上でのメルカリ出品作業は面倒

特に商品の出品作業。
時間はかかる。
狙った位置をクリックしたりドラッグするのが面倒くさい。
少しマウスの位置がずれるとページが戻って、これまでの入力内容がすべてすっ飛ぶ。
そこで。
手作業はやめる。
エクセルに設定した内容がワンクリックで投稿されるようにする。   今回は画像のアップロードまでいけた。

自動化した動作はこんな感じ

こんな感じになった↓
コマンドを打ってエンター!

f:id:chyka:20180201010708p:plain

ブラウザが自動で立ち上がってメルカリが開く。

f:id:chyka:20180201011405p:plain

自動ログインする。

f:id:chyka:20180201011407p:plain

自動で出品ボタンをクリックする。

f:id:chyka:20180201010721p:plain

指定した画像を自動でアップロード。

f:id:chyka:20180201010732p:plain

今回はここまで作成しました。
ワンクリックでブラウザを開く所から画像アップロードまですべて自動で行われます。
一番難関だと思っていたログインと画像アップロードがクリアできたからOK。
あとは簡単でしょう、きっと。

技術的なところの解説

Seleniumのインストール

pip install selenium

Chrome Driverのインストール

ここから自分の環境にあったバイナリをダウンロード。 適切な場所にインストール。

mv ~/Downloads/chromedriver /usr/local/bin

自動で実行する内容のプログラミング

automated.py

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from time import sleep

URL = "https://www.mercari.com/jp/"

# ブラウザを開く。
driver = webdriver.Chrome()

# メルカリにアクセス
driver.get(URL)

# 読み込み遅いかもしれないから3秒待つ。
sleep(3)

# 出品ボタンクリック
driver.find_element_by_link_text("出品").click()

sleep(3)

# 画像hoodie_red.PNGをアップロード
driver.find_element_by_xpath( "//input[@type='file']" ).send_keys("/Users/shun/Downloads/hoodie_red.PNG")

sleep(3)

# ブラウザを終了する。
driver.close()

# プログラム終了
import sys
sys.exit()

プログラム実行!

python automated.py

SQLAlchemyで"case"

SQLAlchemyでcase文がつかえる。

case文とかこれのこと。 CASE WHEN 条件 THEN 値1 ELSE 値2 END

第一引数は必須で、条件と、それが真だった場合に返す値のタプルのリスト。

キーワード引数 else_ は偽だった場合に返す値。

条件にはand、or演算が使えることは確認した。

IN も使えるかと思ったけどどうも想定どおりの挙動ではない。後で調査。

from sqlalchemy.sql.expression import case, and_, or_

年齢から成人・未成年を出力する例。

session.query(
    Person.id,
    Person.name,
    case([(Person.age >= 20, "成人")], else_="未成年")
)

年齢・性別から結婚可能かどうか出力する例。

session.query(
    Person.id,
    Person.name,
    case([or_(and_(Person.age >= 16, Person.sex == "female"), and_(Person.age >= 18, Person.sex == "male")), "結婚可"], else_="結婚不可")
)

例としてはわかりやすいけど、妙な法律だねえ。

SQLAlchemy のサブクエリ

サブクエリのフィールドが見つからないといわれてちょっとハマった。

複数のカゴの中にりんごが複数入っているとする。
すべてのカゴに入っているりんごの総数を集計するサブクエリは以下のように書ける。

りんごのID (apple_id) と総数 (total) をフィールドとしてもたせる。

apple_in_bucket = session.query(
    AppleInBucket.apple_id,
    func.sum(AppleInBucket.count).label("total")
).group_by(
    AppleInBucket.apple_id
).subquery()

この時、apple_in_bucket.apple_idとしてもAttributeErrorを吐く。
サブクエリのフィールドにアクセスするには、cというフィールドを経由する必要がある。
(c はcolumnsの略らしい。もっといいインターフェイスはなかったのだろうか。)
apple_in_bucket.c.totalでりんごの総数をめでたく取得できる。

wordpressを既存のものからコピーで立ち上げる

いつも忘れるのでそろそろ記録を残しておく。

環境

すでにこの環境で動いているWordpressサイトが1つあるとする。

やりたいこと

すでに動いているWordpressをうまくコピーして、新しいサイトを立ち上げる。テーマやプラグインは引き継ぐが、記事やカテゴリなどのコンテンツは引き継がない。

手順

  1. php-fpmの設定ファイルを追加
  2. nginxの設定ファイルを追加
  3. mysqlにユーザーとデータベースを追加
  4. wordpressのディレクトリをコピー
  5. wp-config.phpを設定
  6. php-fpm, nginxの再起動

php-fpmの設定ファイルを追加

/etc/php-fpm.confに include するディレクトリを指定している。そこに既存の設定ファイルがあるはずなのでコピーする。

cp old_fpm.conf new_fpm.conf

pool名とポート番号だけ最低限書き換える。

new_fpm.conf

- [old_site]
+ [new_site]

- listen = 127.0.0.1:9001
+ listen = 127.0.0.1:9002

nginxの設定ファイルを追加

nginxの設定ファイルのディレクトリに既存の設定ファイルがあるはずなのでコピーする。

cp old_nginx.conf new_nginx.conf

ドメイン、ドキュメントルート、ポート番号だけ書き換える。

new_nginx.conf

     - server_name old_env;
     + server_name new_env;
     - root old/wordpress
     + root new/wordpress
  
     location ~ \.php$ {
         - fastcgi_pass   127.0.0.1:9001;
         + fastcgi_pass  127.0.0.1:9002;
     }
}

mysqlにユーザーとデータベースを追加

> create database new_wp_db default character set utf8mb4;
> grant all privileges on new_wp_db.* to wp_db_dev@localhost identified by 'hogehoge';

wordpressのディレクトリをコピー

wp-config.phpを含むディレクトリをまるごとコピーする。

cp -r old_wordpress new_wordpress

wp-config.phpを設定

データベース情報を書き換える。

define('DB_NAME', 'new_wp_db');
define('DB_USER', 'wp_db_dev');
define('DB_PASSWORD', 'hogehoge');

キーやソルトを書き換える。

php-fpm, nginxの再起動

$ sudo /etc/init.d/php-fpm restart
$ sudo /etc/init.d/nginx restart

再起動でOKが出たら、ブラウザからアクセスする。設定画面が表示されていたらおしまい。

wordpress上で画像の編集ができない

環境

現象

Wordpressのライブラリから画像が編集・保存できない。

原因

gdという画像処理用のライブラリがphpから利用できないことが原因だった。

対策

必要なライブラリをインストールするだけ。

$ sudo yum --enablerepo=remi,remi-php56 install gd-last, t1lib
$ sudo yum --disablerepo=* --enablerepo=remi,remi-php56 install php-gd

Pythonでプラットフォームごとに処理を切り替える

プラットフォームで処理を切り替えたいことがたまにある。

sysモジュールを使うと割と簡単にできる。

import sys

# "darwin", "linux", "win32" or "cygwin"
sys.platform

# Pythonのパスを取得したい場合は
sys.executable