Google Colaboratory(Colab)でスクレイピングするときのチートシート


# 目次
- [Beautiful Soupの使用方法](#beautiful-soupの使用方法)
    - [findのコード一覧](#findのコード一覧)
    - [selectのコード一覧](#selectのコード一覧)
    - [セレクタの指定方法一覧](#セレクタの指定方法一覧)
- [Seleniumの使用方法](#seleniumの使用方法)
    - [Seleniumを使うための事前準備](#seleniumを使うための事前準備)
    - [SeleniumとBeautiful Soupを使用する場合](#seleniumとbeautiful-soupを使用する場合)
    - [Seleniumの基本コード](#seleniumの基本コード)
    - [ドロップダウンを選択したいとき](#ドロップダウンを選択したいとき)
    - [Xpathの指定方法一覧](#xpathの指定方法一覧)
    - [タブを変更する場合](#タブを変更する場合)
    - [特定の要素が表示されるまで待機処理](#特定の要素が表示されるまで待機処理)
    - [クリックできないときの処理](#クリックできないときの処理)
- [Pandasを使用してデータを保存する方法](#pandasを使用してデータを保存する方法)
    - [① PandasのデータCSVでダウンロードする](#-pandasのデータcsvでダウンロードする)
    - [② Pandasのデータをマイドライブに格納する](#-pandasのデータをマイドライブに格納する)
    - [③ Pandasのデータをスプレッドシートに反映させる](#-pandasのデータをスプレッドシートに反映させる)

#Beautiful Soupの使用方法

## 文字化け解消方法

`requests`を使用する場合は通常下記のように書くと思いますが、

```python
from bs4 import BeautifulSoup
import requests

res = requests.get(url)
soup = BeautifulSoup(res.content, 'html.parser')
```

これだと文字化けするサイトがあるので、下記にすると文字化けがかなり解消できる。

```python
from bs4 import BeautifulSoup
import requests

res = requests.get(url)
soup = BeautifulSoup(res.content, "lxml", from_encoding='utf-8')
```

## findのコード一覧


| 説明 | コード例 |
|:---|:---|
| 1件検索 | soup.find('li') |
| タグ全検索 | soup.find_all('li') |
| 属性検索 | soup.find('li', href='html://www.google.com/') |
| 複数要素を取得 | soup.find_all(['a','p']) |
| id検索 | soup.find('a', id="first") |
| class検索 | soup.find('a', class_="first") |
| 属性取得 | first_link_element['href'] |
| テキスト検索 | soup.find('dt' ,text='検索ワード') |
| テキスト部分一致の検索 | soup.find('dt' ,text=re.compile('検索ワード')) |
| 親要素を取得 | .parent |
| 次の要素を1件取得 | .next_sibling |
| 次の要素を全件取得 | .next_siblings |
| 前の要素を1件取得 | .previous_sibling |
| 前の要素を全件取得 | .previous_siblings |
| テキスト要素の取得 | .string |

	
## selectのコード一覧
| 説明 | コード例 |
|:---|:---|
| 1件検索 | soup.select_one('cssセレクタ') |
| 全件検索 | soup.select('cssセレクタ') |

## セレクタの指定方法一覧
| 説明 | コード例 |
|:---|:---|
| id検索 | soup.select('a#id') |
| class検索 | soup.select('a.class') |
| classの複数検索 | soup.select('a.class1.class2') |
| 属性検索1 | soup.select('a[class="class"]') |
| 属性検索2 | soup.select('a[href="http://www.google.com"]') |
| 属性検索3 | soup.select('a[href]') |
| 子要素の取得 | soup.select('.class > a[href]') |
| 子孫要素の取得 | soup.select('.class a[href]') |
| n番目の要素の取得 | soup.select('.a:nth-of-type(n)') |

属性要素は検索したい要素に応じて変更する。
`id`,`class`,`href`,`name`,`summary`など。
子要素(1階層下)だけ取得したい場合は`>`を挟み、子孫要素(階層下全て)を取得したい場合は`スペース`を入れる。


#Seleniumの使用方法

##Seleniumを使うための事前準備

Colabで使用する際はSeleniumのダウンロードとUIの仕様ができないので、
その設定が必要になります。

```python
# Seleniumを使用するのに必要なライブラリをダウンロード
!apt-get update
!apt install chromium-chromedriver
!cp /usr/lib/chromium-browser/chromedriver /usr/bin
!pip install selenium

from selenium import webdriver

# ドライバーをUIなしで使用するための設定
options = webdriver.ChromeOptions()
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
driver = webdriver.Chrome('chromedriver',chrome_options=options)
driver.implicitly_wait(10)
```

2022年12月
久しぶりに使おうと思ったらwebdriver.Chromeのオプション引数が
`options`から`chrome_options`に変わっていました。


## SeleniumとBeautiful Soupを使用する場合
使用ケースとしては、Beautiful Soupだけではどうしても要素が取得できない場合に
seleniumuでページを読み込んでからBeautiful Soupで必要な情報を抜きたい場合。

```python
driver.get(url)
html = driver.page_source.encode('utf-8')
soup = BeautifulSoup(html, 'html.parser')
```


## Seleniumの基本コード
| 説明 | コード例 |
|:---|:---|
| URLを開く | driver.get('URL') |
| 一つ前に戻る | driver.back() |
| 一つ前に進む | driver.forward() |
| ブラウザを更新 | driver.refresh() |
| 現在のURLを取得 | driver.current_url |
| 現在のタイトルを取得 | driver.title |
| 現在のウィンドウを閉じる | driver.close() |
| 全てのウィンドウを閉じる | driver.quit() |
| クラスで要素取得 | driver.find_element_by_class_name('classname') |
| IDで要素取得 | driver.find_element_by_id('id') |
| XPATHで要素取得 | driver.find_element_by_xpath('xpath') |
| XPATHでテキスト検索 | driver.find_element_by_xpath('//*[text()="strings"]') |
| XPATHでテキスト部分一致検索 | driver.find_element_by_xpath('//*[contains(text(), "strings")]') |
| 要素をクリック | driver.find_element_by_xpath('XPATH').click() |
| テキスト入力 | driver.find_element_by_id('ID').send_keys('strings') |
| テキストの取得 | driver.find_element_by_id('ID').text |
| 属性の取得(hrefの場合) | driver.find_element_by_id('ID').get_attribute('href') |
| 要素が表示されているか判定 | driver.find_element_by_xpath('xpath').is_displayed() |
| 要素が有効か判定 | driver.find_element_by_xpath('xpath').is_enabled() |
| 要素が選択されているか判定 | driver.find_element_by_xpath('xpath').is_selected() |


### ドロップダウンを選択したいとき
```python
from selenium.webdriver.support.ui import Select

element = driver.find_element_by_xpath("xpath")
Select(element).select_by_index(indexnum) # indexで選択
Select(element).select_by_value("value") # valueの値
Select(element).select_by_visible_text("text") # 表示テキスト
```

## Xpathの指定方法一覧
| 説明 | コード例 |
|:---|:---|
| 全ての要素を選択 | //* |
| 全ての要素を選択 | //a |
| 属性を選択 | @href |
| 複数要素を選択 | [a or h2] |
| idで要素取得 | //*[@id="id"] |
| classで要素取得 | //*[@class="class"] |
| テキスト検索 | //*[text()="strings"] |
| テキストの部分検索 | //*[contains(text(), "strings")] |
| クラスの部分一致 | //*contains(@class, "class") |
| 次のノード取得 | /following-sibling::*[1] |
| 2つあとのa要素の | /following-sibling::a[2] |
| 後ろのノード取得 | /preceding-sibling::*[1] |

[その他ノードの取得方法はこちらを参考にする](https://www.octoparse.jp/blog/essential-for-web-scraping-xpath-introduction/)


## タブを変更する場合

クリックするとページ遷移せず新しいタブができる場合に使用

```python
handle_array = driver.window_handles
driver.switch_to.window(handle_array[1])
```


## 特定の要素が表示されるまで待機処理

```python

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

# ページ上のすべての要素が読み込まれるまで待機（15秒でタイムアウト判定）
WebDriverWait(driver, 15).until(EC.presence_of_all_elements_located)

# ID指定したページ上の要素が読み込まれるまで待機（15秒でタイムアウト判定）
WebDriverWait(driver, 15).until(EC.presence_of_element_located((By.ID, 'ID名')))

# CLASS名指定したページ上の要素が読み込まれるまで待機（15秒でタイムアウト判定）
WebDriverWait(driver, 15).until(EC.presence_of_element_located((By.CLASS_NAME, 'CLASS名')))

# XpathでCLASS名指定したページ上の要素が読み込まれるまで待機（15秒でタイムアウト判定）
WebDriverWait(driver, 15).until(EC.presence_of_element_located((By.XPATH, 'xpath')))
```


## クリックできないときの処理

```python
target = driver.find_element_by_xpath('xpath')
driver.execute_script("arguments[0].click();", target)
```

# Pandasを使用してデータを保存する方法


## データフレームを作成してデータを追加していく方法
```python
import pandas as pd
columns = ['項目1', '項目2', '項目3', '項目4', '項目5']
df = pd.DataFrame(columns=columns)

# データ取得の処理
se = pd.Series([data1, data2, data3, data4, data5], columns)
df = df.append(se, columns)
```

上記のようにデータフレームを作成し後、データを保存する方法には下記の3パターンがあります。

① CSVでダウンロードする
② マイドライブに格納
③ スプレッドシートに反映させる

## ① PandasのデータCSVでダウンロードする
```python
from google.colab import files

filename = 'filename.csv'
df.to_csv(filename, encoding = 'utf-8-sig') 
files.download(filename)
```


## ② Pandasのデータをマイドライブに格納する
```python
from google.colab import drive

filename = 'filename.csv'
path = '/content/drive/My Drive/' + filename

with open(path, 'w', encoding = 'utf-8-sig') as f:
  df.to_csv(f)
```


## ③ Pandasのデータをスプレッドシートに反映させる

```python
!pip install gspread

from google.colab import auth
from oauth2client.client import GoogleCredentials
import gspread
import pandas as pd

# 認証処理
auth.authenticate_user()
gc = gspread.authorize(GoogleCredentials.get_application_default())

ss_id = 'スプレッドシートのID'
workbook = gc.open_by_key(ss_id)

# パラメーターを指定してシートへ張り付ける場合
workbook.values_update(
  # sheet!A1などセルを指定
  target_cell,
  params={
      'valueInputOption': 'USER_ENTERED'
  },
  body={
      'values': [df.columns.values.tolist()] + df.values.tolist()
  }
)
```



【参考サイト】
[BeautifulSoup4のチートシート(セレクターなど）](https://python.civic-apps.com/beautifulsoup4-selector/)
[Python3メモ - BeautifulSoup4のあれこれ](https://szarny.hatenablog.com/entry/2017/07/11/144503)
[WebスクレイピングのためのCSSセレクタの基本](https://gammasoft.jp/support/css-selector-for-python-web-scraping/)
[Selenium webdriverよく使う操作メソッドまとめ](https://qiita.com/mochio/items/dc9935ee607895420186)
[XPathとは？XPathの基本知識を学ぼう！](https://www.octoparse.jp/tutorial/xpath/)
[Webスクレイピングに不可欠！Xpathのまとめ](https://www.octoparse.jp/blog/essential-for-web-scraping-xpath-introduction/)
[gspreadライブラリの使い方まとめ！Pythonでスプレッドシートを操作する](https://tanuhack.com/library-gspread/)