初めてPythonで作品を作ってみました！

## はじめに

初めまして！初投稿です！
昨日初めてPythonで作った作品が完了したので、今日Githubに投稿してQiitaも初めて登録して投稿してみました！
作成したものはスクレイイングツールで、不動産情報サイトのSuumoから指定した条件の物件情報を取得してcsvに書き出すことができます。　

## 作った作品 
まだまだ初心者でコードがぐちゃぐちゃかもしれません！すみません。。。


https://github.com/MaronMori/scrapingproperty.git

main.pyを実行すると起動します。　
他のpyファイルはmainの中のリストで使用したい情報を全てサイトから移すのが面倒だったので、スクレイピングしたファイルです。他はテストで使用しました。 
csvファイルはmain.pyで作成したものです。




## 使用した言語 
Python
## 使用したディレクトリ　
- selenium
- pandas
- tkinter
## 今回の作品を作った経緯　
現在大学卒業にカナダに留学していてComputer Scienceを専攻しています。その中でPythonの授業があり、Pythonは独学でも勉強していたのでそろそろ何か作品を作ろうかなと思い何を作ろうか迷っていました。　
そこで一回スクレイピングツールを作ってみるといいと聞いたので、スクレイピングに関するYouTubeの動画で基礎的な部分を学んでから今回の作品を作りました。

そしてお金を稼がないといけない状況でして、何かPythonで稼げる方法はないかと調べたところスクレイピングが難易度も低くて稼ぎやすいとあったのももう一つの理由です。


## 作ってみた感想　　
今回のツールは完成するまでまる2日かかってかなり疲れました。エラーももちろんたくさん出て、作成時はかなりイライラしていましたが実際に働いているエンジニアたちはいつもこういう苦労をしているんだなと感じることもできました。しかしhtmlやcssなどと違いロジックをしっかり考えてコーディングしていくので、どちらかというとこういう論理的に考えて作成しているのは自分的に好きな方だと思いました。 
　
そして何度かトライアンドエラーしていく中で、結構スクレピングでも時間が掛かってしまうんだなと思いました。（手作業でやるよりかは圧倒的に早いですが）しかし実際に実行してみて、csvに書き込んだ出力結果を見た時はかなり感動して嬉しかったです。　　

おそらくですが最初の作品にしては難易度が高い方だったかもしれませんが、この経験を活かし他にもう少し簡単なアプリケーション（To Doリストなど）も作っていこうかなと思います。　　

## 苦労したところ 
### 特定のテキストを含んだ要素の取得　
find_elementで要素を指定するときに、tkinterのGUIでユーザーが指定した物件の条件が含まれている要素を指定するのがやり方がわからなくて困りました。ChatGPTに聞いてみるとそういう場合はXPathを使用するといいと教えてもらい、XPathで特定のテキストを含んだ要素を取得することできました。XPathはちょうど学校でPATHについても学んだのでそれを活かして自分でXPathを工夫しながら活用することができました。 

例：　
```Python
tokyo_size = browser.find_element(By.XPATH, f"//li[label[contains(text(), '{size}')]]")
        tokyo_size_input = tokyo_size.find_element(By.TAG_NAME, 'input')
        tokyo_size_input.click()
```

### 要素が古くなり参照できない 
Suumoの物件情報で1ページに収まりきらない場合、次のページに行く必要があったのでそれをwhile文で実行していました。そのwhile文の中でマイページ毎にスクレイピングしていて、while文が終わるとスクレイピングした要素をデータフレームに入れるようにしていました。しかしそのようにやると、まだよくわかっていないのですがどうやらページが切り替わるとすでに取得した要素が「古い」とみなされ参照できなくなるそうです。　
ここでかなりつまずきましたが、データフレームへの入力もページごとのするようにwhile文内に移動したら解決できました。　
例：　
```Python
while len(rent_prices) < selected_value:
        rent_prices = browser.find_elements(By.CLASS_NAME, 'detailbox-property-point')
        management_fees = browser.find_elements(By.CSS_SELECTOR, 'tr > td.detailbox-property--col1 > div:nth-child(2)')
        deposit_fees = browser.find_elements(By.CSS_SELECTOR, '.detailbox-property--col2 > div:nth-child(1)')
        key_monies = browser.find_elements(By.CSS_SELECTOR, '.detailbox-property--col2 > div:nth-child(2)')
        size_houses = browser.find_elements(By.XPATH, f"//tr/td/div[contains(text(), '{size}')]")
        ages_house = browser.find_elements(By.XPATH, '//td/div[contains(text(), "築")]')
        distances = browser.find_elements(By.CSS_SELECTOR, '.detailnote > .detailnote-box:nth-child(1)')
        addresses = browser.find_elements(By.CSS_SELECTOR, 'div.detailbox-property > table > tbody > tr > td:nth-child(5)')
        name_houses = browser.find_elements(By.CLASS_NAME, 'property_inner-title')
        url_houses = browser.find_elements(By.CSS_SELECTOR, '.property_inner-title > a')
        pictures_house = browser.find_elements(By.CSS_SELECTOR, ".cassette_carrousel > .cassette_carrousel-thumblist > .cassette_carrousel-item > li > img")

        rent_prices = rent_prices[:selected_value]
        management_fees = management_fees[:selected_value]
        deposit_fees = deposit_fees[:selected_value]
        key_monies = key_monies[:selected_value]
        size_houses = size_houses[:selected_value]
        ages_house = ages_house[:selected_value]
        distances = distances[:selected_value]
        addresses = addresses[:selected_value]
        name_houses = name_houses[:selected_value]
        url_houses = url_houses[:selected_value]
        pictures_house = pictures_house[:selected_value]

        # 家賃
        for rent_price in rent_prices:
            prices_list.append(rent_price.text)
            print(rent_price.text)
        df['家賃'] = prices_list
        # 管理費
        for management_fee in management_fees:
            manage_fee_list.append(management_fee.text)
            print(management_fee.text)
        df['管理費'] = manage_fee_list
        # 敷金
        for deposit_fee in deposit_fees:
            deposit_fee_list.append(deposit_fee.text)
            print(deposit_fee.text)
        df['敷金'] = deposit_fee_list
                        .
                        .
                        .
```



### 要素の指定 
find_elementsで要素を指定するのは常に苦戦していました。例えばhtmlでclassが指定されてればいいのですが、classがないタグもあるので余計な要素も取得してしまうことがありました。　
ほとんどの場合cssセレクターでかなり具体的に指定したら、取得したいものをしっかり取得できるようになりました。 

## 今後の改善余地がありそうな点 
今回のスクレイピングツールでもっと改良できそうな事項を挙げるとこんな感じです。　
- GUIのサイズやデコレーション
- もっと詳細な物件の条件
- コメントをしっかりと書く
- 今回は東京だけなので他の地域も可能にする
- いらないコードの削除（どれが必要ないのかわからなくて消すのが怖いのでそのままです。。。）
 
## まとめ　
初めての作品ですがかなり満足感と達成感があって楽しかったです。　
今後もこの経験を活かしもっと他の作品もトライしてみたいと思います。
自分のポートフォリオも作らないといけないので次はhtmlとcssを頑張ります。