Pythonでやる奴

Python出来る→機械学習も出来る→価値UPで年収UPでやりがいUP→いつかは田舎暮らししたい男のブログ

LinuC (LPIC) Lv1 101試験の合格体験記

f:id:ring-star4610:20180818193504p:plain
LinuC

Pythonブログと言いつつも、Linuxも知っていて損は無いため 短期集中で勉強して第一歩となるLv1(の中の101試験)を受けてきたので その体験記でも書いておく。


なぜ受けようと思ったか?

理由は色々ある

  1. 最近、ラズベリーパイ に興味を持っている。

    Linuxの知識も、Pythonの知識も必要となる。そしてやっていて楽しそうである。

  2. awsの資格もあるのでLinuxも持っていて損はない

    → 今年の5月頃にawsのアソシエイト資格を取ったが、コレまたサーバ(Linux)の知識が必要だと感じたから。

  3. 最もキャリアップ(昇級や転職)につながったベンダーニュートラル試験堂々一位

    eng-entrance.com

仕事では今の所一切関係ありませんが、レベルアップしていくことで仕事の幅を広げられるようにしたい。


本題

試験名:LinuC レベル1 101試験

スコア:600点 / 800点

合格ライン:520点

セクション別の合格率

結果:合格


勉強方法

Ping-tの無料コンテンツ、最強WEB問題集LinuC/LPIC Lv1-101 (Ver4.0)を繰り返し実施

ping-t.com

全部で690問と大変多いですが、短期間(1,2週間)でやることで暗記しました。

問題の合否によって、銅・銀・金と変化していく仕組みです。

要は間違えずに複数回正解すれば金となるので、全ての問題が金となるように解き続けます。

銅→銀の段階では、分野別に処理していくのも手ですが、銀→金の時は、 全分野からのランダム出題にした方が、良いかなと個人的には思ったり。


実際の試験

選択式ではなく、記述も出ました。(私の場合、60門中の5問くらいだったかな。)

コレが意外と厄介でした。なので、少しはコマ問LinuC/LPIC Lv1-101 (Ver4.0)もやっておいて損はないかと。

LD_LIBRARY_PATHなんて思い出せんて。。。

また、問題文に関しても、Ping-tの問題文と比べると、試験の問題文は ちょっとだけ分かりにくいです。

別の方の体験記で、「問題文は英文でも見れる」とありましたが、

私が受けた、LinuC試験は英文にするメニューはなかったです。

LPICだけなのかな??まぁ英語で見れた所で分からんわ。

試験終了後→そのまま画面でアンケート入力→最後に合否が表示 という流れです。

やっぱりというかなんて言うか、パッケージ管理のあたりのオプションが多彩過ぎて完璧に覚えられず、如実に結果に現れてしまいました。


何だかんだ101は受かったので、次は102の試験を目指したいと思います。

会社からの奨励金がレベル2からしか出ないので、レベル2までは絶対取ります!

【金】ヾ(¥∀¥;ヾ)オカネ♪

補足:試験のバウチャーが上記Ping-tから購入できます。1000円ちょっとですが安くなるのでオススメです。

jsonファイルをcsv(Excel)データに変換

「仕事ではじめる機械学習」を読んだ。

正直、まだまだ理解できていないところが多いが、 後半の章は、実際に手を動かしながら説明を読み進めていく事で、 機械学習をしていく「流れ」みたいな感覚は掴めた。

(※本に記載のコードは、極一部ミスがあるため、エラーで詰まったらgithubに上がっているコードを確認するべし。)

仕事ではじめる機械学習

仕事ではじめる機械学習

その中で、機械学習ではないが、jsonファイルをcsvで読めるようにするコードが、 いつか自分で使いそうだと思ったので、メモとして残しておく。(一部アレンジ)

import glob
import json
import pandas
import pandas.io.json

json_list = []

# globでjsonを読み込み(以下ではresultフォルダ内のjsonファイルを全て読み込み)
for filename in glob.glob("result/*.json"):
    json_data = json.loads(open(filename).read())
    json_list.append(json_data)
    
# 変換対象が少数なら以下の方がシンプルか
# df = pandas.read_json("hoge.json")
    
# json_normalizeでDataFrameに変換する
df = pandas.io.json.json_normalize(json_list)

# csv形式に変換する
csv_data = df.to_csv()

# (Windows対策)Excelに読みこませる場合、CP932でエンコードする
csv_data = csv_data.encode("cp932", "ignore")

# 書き込み
fp = open("hoge.csv", "wb")
fp.write(csv_data)
fp.close()

最小構成だと以下の記述で済む

import pandas

df = pd.read_json("hoge.json")

csv_data = df.to_csv("hoge.csv")

機械学習については、もっと初歩の用語から手をつけないとついていけないかな、と感じた。 一通りの説明はあるのだが、頭に入ってこないというか・・・。 とりあえず、初学者向けの本をもう少し読み進めつつ、分からないなりにもコードの記述があれば ひたすら手を動かして行ってみよう。

pythonでsqlite(チュートリアル)

ちょっとしたDB?それならSQLite(読み:エスキューエルライト)でしょう。

  • まずはインポート
import sqlite3
  • DBファイルの作成
conn = sqlite3.connect('test_sqlite.db')

※コーディング中など、何度もクエリを実行する必要がある場合は、インメモリ機能を使うと良い。 そうすることで、既にそのテーブル存在してますよ等々のエラーが表示されなくなる。 上記の代わりに以下を用いる。

conn = sqlite3.connect(':memory:') 
  • カーソルの作成
curs = conn.cursor()
  • table作成
curs.execute(
    'CREATE TABLE persons(id INTEGER PRIMARY KEY AUTOINCREMENT, name STRING)')
conn.commit()
# 以下、commitを行うタイミングは各自で判断願います。
  • データ挿入
curs.execute(
    'INSERT INTO persons(name) values("Mike")'
)
conn.commit()
  • データ更新
curs.execute('UPDATE persons set name= "Michel" WHERE name = "Mike"')
conn.commit()
  • データ選択
curs.execute('SELECT * FROM persons')
print(curs.fetchall())
  • データ削除
curs.execute('DELETE FROM persons WHERE name = "Michel"')
conn.commit()
  • 後処理
curs.close()
conn.close()

上記コードを纏めたものは以下よりどうぞ

続きを読む

メルカリをスクレイピングした結果をcsvファイルに書き込む

前回の続きです。 pypython.hatenablog.com

所々コードを変えていますが、メインはcsvに書き込む際の データの二次元配列格納、それを受けてのcsvへの書き込みです。

from selenium import webdriver
import csv

# 件数表示用
count = 0
# 検索結果格納
result = []


def main():
    # chromeDriverの位置
    driver = webdriver.Chrome('/usr/local/bin/chromeDriver')

    set_search_conditions(driver)
    r = get_item(driver)
    # csv への書込み
    writer_csv(r)
    driver.close()


def set_search_conditions(driver):
    # macbook pro を5万〜20万かつ販売中のものを検索条件としている。
    driver.get('https://www.mercari.com/jp/'
               'search/?sort_order=&keyword=macbook+pro'
               '&category_root=7&category_child=&brand_name='
               '&brand_id=&size_group='
               '&price_min=50000&price_max=200000&status_on_sale=1')


def get_item(driver):
    """
    検索結果を取得し、二次元配列のリストで返す
    """
    global result
    global count
    search_limit = 100

    items = driver.find_elements_by_class_name('items-box')
    for item in items:
        if count == 0:
            # 最初にヘッダを用意する
            result.append(['No', 'Link', 'Title', 'ImageLink', 'Price'])

        result.append([count + 1,  # No
                       # Link
                       item.find_element_by_tag_name('a').get_attribute('href'),  
                       # Title
                       item.find_element_by_tag_name('h3').text,  
                       # ImageLink
                       item.find_element_by_tag_name('img').get_attribute('data-src'),  
                       # Price
                       item.find_element_by_class_name('items-box-price').text])  

        count += 1
        if count == search_limit:
            break

    # やりすぎ注意
    if count == search_limit:
        return result

    # 次のページがあれば処理を繰り返す
    next_page = driver.find_element_by_class_name('pager-next')
    if next_page.is_displayed() is True:
        next_page.find_element_by_tag_name('a').click()
        get_item(driver)

    return result


def writer_csv(data):
    f = open('result.csv', 'w')
    w = csv.writer(f)
    w.writerows(data)
    f.close()


if __name__ == '__main__':
    main()

csvはこのようになりました。上手くいきました。 f:id:ring-star4610:20180728065958p:plain


最初、DictWriter、writeheaderを使う方法を前提としていたのだが、(参考にしているサイトがそう書いていたため) ヘッダ部も二次元配列に落とし込むことで、より短いコードで書けた。これがベストなのかは分からないが・・・。 また、データを2次元配列に書き込む方法が最初分からず苦労したが、対話モードで試していくとあっさり解決した。対話モードはヘルプも簡単に出せるし、今後積極的に使っていこう思う。

コードに行が表示されるようにデザインを変更

[2018/07/28 追記]

ちょっと見づらさを感じたので、行表示はやめ、

以下のスタイルをデザインCSSに追加しました。

.code{
font-size: 12px;
background-color: #002B36;
color: #cccccc;
}

 

 

ちょうどいい感じのものを見つけたので参考にしました。

 

am1tanaka.hatenablog.com

メルカリをスクレイピングして商品リンク、画像、価格を取得する

タイトルの通り!

要素の取得方法など勉強がてら、みんな大好きスクレイピングを実装しました。 ここまで出来ればcsvに吐き出すことは余裕のよっちゃんよね。


from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
# 件数表示用
count = 0


def main():
    # chromeDriverの位置
    driver = webdriver.Chrome('/usr/local/bin/chromeDriver')

    set_search_conditions(driver)
    get_item(driver)

    driver.close()


def set_search_conditions(driver):
    driver.get('https://www.mercari.com/jp/')
    # 検索窓の要素を取得
    s = driver.find_elements_by_name('keyword')
    """
    レスポンシブ対応のためkeyword要素が2つある。(スマホ、PC)
    ここでは、PCサイトを前提とするため、2つ目の要素を使用する。
    """
    # 検索キーワードを入力
    s[1].send_keys('iPhoneX')
    # Enterキーを入力する
    s[1].send_keys(Keys.ENTER)

    # 詳細条件を設定
    """ カテゴリ
    1 : レディース
    2 : メンズ
    ...
    7 : 家電・スマホ・カメラ
    """
    # 親カテゴリ
    # Selectクラスを使うと容易にプルダウンメニューを選択できる。
    category_root = Select(driver.find_element_by_name('category_root'))
    category_root.select_by_visible_text('家電・スマホ・カメラ')
    # value値でも指定可能
    # category_root.select_by_value('7')

    # 子カテゴリ
    category_child = driver.find_element_by_xpath(
        '/html/body/div[1]/main/div[2]/form/div[2]/div[2]/div[2]/div[8]/select/option[2]')
    category_child.click()
    """ 下記の入力方法も出来るかと思ったが、要素が複数あるため方法分からず。
    スマートフォン/携帯電話のカテゴリを選択
    category_child.select_by_visible_text('スマートフォン/携帯電話')
    value値でも(ry
    category_child.select_by_value('100')
    """

    # スマートフォン本体のチェックボックスをon
    category_chkbox = driver.find_element_by_xpath(
        '/html/body/div[1]/main/div[2]/form/div[2]/div[2]/div[3]/div[91]/div[1]/label')
    category_chkbox.click()

    # submit
    submit = driver.find_element_by_tag_name('button')
    submit.click()
    """
    ここまで長々と、検索設定してきたが、
    予め設定した条件で一度検索かけると、URLに
    検索パラメータが反映されるので、検索結果が欲しいだけなら
    上記の個々設定をプログラムでやる必要はない。
    seleniumの学習の一貫で調べたまで
    """


def get_item(driver):
    """
    検索結果を取得する
    """
    global count
    search_limit = 100

    items = driver.find_elements_by_class_name('items-box')
    for item in items:

        count += 1
        if count > search_limit:
            break

        print('----------------------------------------------------------')
        print('#', count)
        # 商品リンク
        print(item.find_element_by_tag_name('a').get_attribute('href'))
        # 商品タイトル
        print(item.find_element_by_tag_name('h3').text)
        # 商品画像
        print(item.find_element_by_tag_name('img').get_attribute('data-src'))
        # 価格
        print(item.find_element_by_class_name('items-box-price').text)

    # やりすぎ注意
    if count > search_limit:
        return

    # 次のページがあれば処理を繰り返す
    next_page = driver.find_element_by_class_name('pager-next')
    if next_page.is_displayed() is True:
        next_page.find_element_by_tag_name('a').click()
        get_item(driver)


if __name__ == '__main__':
    main()

リファクタリングの余地あり!!笑

なお結果はこんな感じで出力されます。

----------------------------------------------------------
# 1
https://item.mercari.com/jp/m38547876320/
iPhoneX
https://static-mercari-jp-imgtr2.akamaized.net/thumb/photos/m38547876320_1.jpg?1532585075
¥ 90,000
----------------------------------------------------------
# 2
https://item.mercari.com/jp/m25321697532/
iPhone 7 Plus Jet Black 128 GB SIMフリー
https://static-mercari-jp-imgtr2.akamaized.net/thumb/photos/m25321697532_1.jpg?1532585087
¥ 60,000
----------------------------------------------------------

(省略)

----------------------------------------------------------
# 100
https://item.mercari.com/jp/m22103423090/
SIMフリー iPhoneX 64GB
https://static-mercari-jp-imgtr2.akamaized.net/thumb/photos/m22103423090_1.jpg?1532431094
¥ 85,000

プロセスは終了コード 0 で完了しました

所感:関数の構造がこれが正解なのか分からん。また、xpathで書いているところの「これじゃ駄目だ」感が拭えない。件数が0件だった時、その他エラーハンドリングまでは全く考慮されていない。 これ作るのに約半日かかった。まだまだ。

次はcsvやDBに入れるまでをやってみようと思います。

vagrant コマンドメモ

Vagrantfileに設定が記述済み

 

環境の起動

$ vagrant up

ステータス確認

$ vagrant status

Current machine states:

main                      running (virtualbox)
server1                   running (virtualbox)
server2                   running (virtualbox)

プロビジョニングし直し(vagrant upやstatusで何らかのエラーが出てたら先ずやってみる)

# 名前を指定すると指定されたサーバーのみが対象になる。
$ vagrant provision server1

環境だけ立ち上げ直し(statusで "not created” になっていた時など)

$ vagrant up server1

環境の再起動

$ vagrant reload server1

環境の停止(身近な例で言うとシャットダウン)

$ vagrant halt
# $ vagrant upでまた起動できる。

環境の削除(もう使わないときに)

$ vagrant destroy