otaniteruaki / menta_python

0 stars 0 forks source link

課題2について #6

Open otaniteruaki opened 3 years ago

otaniteruaki commented 3 years ago

米谷さんのテンプレートコードについて

import os
from selenium.webdriver import Chrome, ChromeOptions
import time
import pandas as pd

# Chromeを起動する関数

def set_driver(driver_path, headless_flg):
    # Chromeドライバーの読み込み
    options = ChromeOptions()

    # ヘッドレスモード(画面非表示モード)をの設定
    if headless_flg == True:
        options.add_argument('--headless')

    # 起動オプションの設定
    options.add_argument(
        '--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36')
    # options.add_argument('log-level=3')
    options.add_argument('--ignore-certificate-errors')
    options.add_argument('--ignore-ssl-errors')
    options.add_argument('--incognito')          # シークレットモードの設定を付与

    # ChromeのWebDriverオブジェクトを作成する。
    return Chrome(executable_path=os.getcwd() + "/" + driver_path, options=options)

# main処理

def main():
    search_keyword = "高収入"
    # driverを起動
    if os.name == 'nt': #Windows
        driver = set_driver("chromedriver.exe", False)
    elif os.name == 'posix': #Mac
        driver = set_driver("chromedriver", False)
    # Webサイトを開く
    driver.get("https://tenshoku.mynavi.jp/")
    time.sleep(5)

    try:
        # ポップアップを閉じる
        driver.execute_script('document.querySelector(".karte-close").click()')
        time.sleep(5)
        # ポップアップを閉じる
        driver.execute_script('document.querySelector(".karte-close").click()')
    except:
        pass

    # 検索窓に入力
    driver.find_element_by_class_name(
        "topSearch__text").send_keys(search_keyword)
    # 検索ボタンクリック
    driver.find_element_by_class_name("topSearch__button").click()

    # ページ終了まで繰り返し取得
    exp_name_list = []
    # 検索結果の一番上の会社名を取得
    name_list = driver.find_elements_by_class_name("cassetteRecruit__name")

    # 1ページ分繰り返し
    print(len(name_list))
    for name in name_list:
        exp_name_list.append(name.text)
        print(name.text)

# 直接起動された場合はmain()を起動(モジュールとして呼び出された場合は起動しないようにするため)
if __name__ == "__main__":
    main()
otaniteruaki commented 3 years ago

発生したエラー

(venv) TO-mac:Lesson2 teruaki.otani$ python sample.py 
Traceback (most recent call last):
  File "/Users/teruaki.otani/Desktop/Python_menta/Lesson2/venv/lib/python3.8/site-packages/selenium/webdriver/common/service.py", line 72, in start
    self.process = subprocess.Popen(cmd, env=self.env,
  File "/Users/teruaki.otani/.pyenv/versions/3.8.3/lib/python3.8/subprocess.py", line 854, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/Users/teruaki.otani/.pyenv/versions/3.8.3/lib/python3.8/subprocess.py", line 1702, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: '/Users/teruaki.otani/Desktop/Python_menta/Lesson2/chromedriver'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "sample.py", line 72, in <module>
    main()
  File "sample.py", line 37, in main
    driver = set_driver("chromedriver", False)
  File "sample.py", line 26, in set_driver
    return Chrome(executable_path=os.getcwd() + "/" + driver_path, options=options)
  File "/Users/teruaki.otani/Desktop/Python_menta/Lesson2/venv/lib/python3.8/site-packages/selenium/webdriver/chrome/webdriver.py", line 73, in __init__
    self.service.start()
  File "/Users/teruaki.otani/Desktop/Python_menta/Lesson2/venv/lib/python3.8/site-packages/selenium/webdriver/common/service.py", line 81, in start
    raise WebDriverException(
selenium.common.exceptions.WebDriverException: Message: 'chromedriver' executable needs to be in PATH. Please see https://sites.google.com/a/chromium.org/chromedriver/home

原因

chromedriver をカレントディレクトリに配置してないことが原因?

File "sample.py", line 37, in main
    driver = set_driver("chromedriver", False)
  File "sample.py", line 26, in set_driver
    return Chrome(executable_path=os.getcwd() + "/" + driver_path, options=options)

ここでchromedriverのアプリファイルがないと言われているから。

解決

macに入っているchromeアプリのバージョンを確認すると、ver90だったので、同じバージョンのchromedriverを ダウンロードして、カレントディレクトリに格納した。 https://chromedriver.chromium.org/downloads

otaniteruaki commented 3 years ago

対象の箇所

try:
        # ポップアップを閉じる
        driver.execute_script('document.querySelector(".karte-close").click()')
        time.sleep(5)
        # ポップアップを閉じる
        driver.execute_script('document.querySelector(".karte-close").click()')
    except:
        pass

try文

構文については以下の通り。例外が発生する場合の処理に使う。

try: 
    例外が発生するかもしれないが、実行したい処理。
except エラー名:
    例外発生時に行う処理

今回はポップアップが表される場合は、それを閉じる処理が記載されている。(tryの処理)

ポップアップが表示されない場合は(例外の場合)は、pass(無視)して進む。(exceptの処理)。 ちなみに、except=例外という意味。

driver.execute_script / dcument.querySelector()について

driver.execute_script('document.querySelector(".karte-close").click()')

dcument.querySelector()について

「querySelector()」は、JavaScriptから任意のHTML要素を検出・取得することができるメソッド。 簡単に言うと「querySelector()」だけであらゆるHTML要素を取得することができる。

使い方は以下の通り。

一般的には、対象となる範囲にquerySelector()を実行することになります。

document.querySelector( CSSセレクタ )

この場合、document全体に対してquerySelector()を実行することになります。引数にはjQueryで使うようなCSSセレクタを指定することで、任意のHTML要素を取得することができるようになります。

注意点としては、最初に合致したHTML要素を取得した時点でプログラムは終了するという点です。

つまり、複数の要素を取得するには自作のループ処理を作成するか、後述する「querySelectorAll()」を使う必要があります。

詳細は以下の記事。 https://www.sejuku.net/blog/70581

driver.execute_script()について

driver.execute_script(...)

で JavaScript を実行することができます。 これでスクロールとスクリーンショットを繰り返すこともできます。

otaniteruaki commented 3 years ago

zip()関数について

forループで複数のリストの要素を取得 forループの中で複数のイテラブルオブジェクト(リストやタプルなど)の要素を同時に取得して使いたい場合は、zip()関数の引数にそれらを指定する。

names = ['Alice', 'Bob', 'Charlie']
ages = [24, 50, 18]

for name, age in zip(names, ages):
    print(name, age)
# Alice 24
# Bob 50
# Charlie 18

以下を参照 https://note.nkmk.me/python-zip-usage-for/

otaniteruaki commented 3 years ago

課題2

この課題はマイナビにアクセスしてキーワード検索を行い結果を取得するものです。 説明動画:https://youtu.be/vNJ5DcrdvhM Seleniumの基本:https://techacademy.jp/magazine/28392 Seleniumの応用:https://tanuhack.com/selenium/#URL Pandasの基本:https://note.nkmk.me/pandas/ ログ出力(テキストファイル出力):https://note.nkmk.me/python-file-io-open-with/

サンプルコードは、検索結果の1番上の会社名を取得するようになっています。 下記の課題に従って、レベルアップさせてみましょう。

Seleniumは副業案件においては、非常に重要な技術です。これを習得すれば月5万円程度の収入を得ることが可能です。 頑張って学習してみましょう!

1 難易度★★☆☆☆ 会社名を取得して画面にprint文で表示してみましょう。

2 難易度★★★☆☆ for文を使って、1ページ内の3つ程度の項目(会社名、年収など)を取得できるように改造してみましょう

3 難易度★★★☆☆ 2ページ目以降の情報も含めて取得できるようにしてみましょう

4 難易度★★☆☆☆ 任意のキーワードをコンソール(黒い画面)から指定して検索できるようにしてみましょう

5 難易度★★★★☆ 取得した結果をpandasモジュールを使ってCSVファイルに出力してみましょう

6 難易度★★☆☆☆ エラーが発生した場合に、処理を停止させるのではなく、スキップして処理を継続できるようにしてみましょう (try文)

7 難易度★★☆☆☆ 処理の経過が分かりやすいようにログファイルを出力してみましょう ログファイルとは:ツールがいつどのように動作したかを後から確認するために重要なテキストファイルです。 ライブラリを用いることもできますが、テキストファイルを出力する処理で簡単に実現できるので、試してみましょう。 (今何件目、エラー内容、等を表示)

8 難易度★☆☆☆☆ Chromeドライバーがバージョンアップの際に自動で更新されるようにしてみましょう。 参考:https://qiita.com/YoshikiIto/items/000f241f6d917178981c

9 難易度★★☆☆☆ 検索時等にWeb画面を更新する処理はurlにより制御されます。 そのため、検索窓を使用せずにURLを直接変更することでも検索結果を取得することが可能です。 URLのうち、検索ワードを制御している部分を見つけて、直接プログラムにて修正し 検索結果を表示させてみましょう。 参考:https://webtan.impress.co.jp/e/2012/04/26/12663