【Python】Google検索するコマンドを自作してみる

# 経緯
応用情報技術者試験のお勉強で横文字がたくさん出てきて、 **「この単語の意味なんだっけ？」** ってなることが多い。
あれだよあれ、喉元まで出てきてるんだけどね。

なので**ググるほどでもないけど、意味をちょっくら調べたいとき**にターミナル上で調べるコマンドを作ってみようと思った。

> ちょっくら調べたいが重要

実際、ターミナルから調べるようなコマンドは誰かが作ってるのでそれを使えばいい話ではあるんだけども、結果は1,2行くらいで良いのだ。

https://github.com/jarun/googler


# 作ってみる

googleで調べたときに出てくる、ボックス？（なんて言うのかわからないので教えてほしい）みたいなやつは要約して単語の意味を教えてくれる。

![スクリーンショット 2023-02-08 19.23.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/777324/96c7d648-df3d-b389-9ad7-17bedf28f191.png)

`python`で調べたら
`Pythonはインタープリタ型の高水準汎用プログラミング言語である。 ウィキペディア`って出してくれるみたいに。

今回はこれを利用したい。

https://ascii.jp/elem/000/000/990/990922/

## 環境

先に環境だけ

| System | Version |
| :-: | :-: |
| OS | MacOS Monterey(12.1) |
| zsh | zsh 5.8 (x86_64-apple-darwin21.0) |
| Python | Python 3.9.0 |
| pip | pip 22.2.2 |
| conda | conda 4.10.3 |
| selenium | selenium 4系(4.3.0) |


## プログラム

https://github.com/sho-yoshikawa/ggl

### google検索

`Python`のwebスクレイピング機能を使って書いてみる。

```python:main.py
from selenium import webdriver
from selenium.webdriver.common.by import By
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.service import Service

# webdriver-managerのログが出力されるので消す
import logging
logging.getLogger('WDM').setLevel(logging.NOTSET)

options = webdriver.ChromeOptions()
options.add_argument("--headless")
service=Service(ChromeDriverManager().install())
b = webdriver.Chrome(service=service, options=options)

input_word = "python"
url = "https://google.com/search?q=" + input_word
try:
    b.get(url)
    div = b.find_element(By.XPATH, "//div[@class='kno-rdesc']")
    span = div.find_element(By.TAG_NAME, "span")
    print(span.text)
except:
    print("could not find.")

```

google検索は`https://google.com/search`がパスで、
`?q={word}`でクエリになる。

`div`タグの`kno-rdesc`ってクラスのところに答えが書いてあるのでそれを`XPATH`使って持ってくる。

![スクリーンショット 2023-02-08 19.28.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/777324/32ebc79b-cc11-59a0-1ab0-b69e3adc4256.png)

```zsh:Terminal
python main.py

>> Pythonはインタープリタ型の高水準汎用プログラミング言語である。
```
出てきた。

これをコマンドライン引数から持ってこれるようにする。
`python`は`sys`パッケージを使う。

```python:main.py
...
...

import sys
input_word = sys.argv[1]
url = "https://google.com/search?q=" + input_word
try:
    b.get(url)
    div = b.find_element(By.XPATH, "//div[@class='kno-rdesc']")
    span = div.find_element(By.TAG_NAME, "span")
    print(span.text)
except:
    print("searching wiki...")
```

第一引数に与える。

```zsh:Terminal
python main.py "python"
```

しかし、googleのボックスが出てこないような単語検索がたまにある。

![スクリーンショット 2023-02-08 19.47.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/777324/19e3526d-ad93-d37b-16d9-f4bce729379a.png)

2個目の検索結果に答え書いてあるのに。。
なので、`wikipedia`に頼ります()

### wiki

```python:main.py
...
...

input_word = sys.argv[1]

def google(input_word):
	url = "https://google.com/search?q=" + input_word
	try:
		b.get(url)
		div = b.find_element(By.XPATH, "//div[@class='kno-rdesc']")
		span = div.find_element(By.TAG_NAME, "span")
		print(span.text)
		return True
	except:
		print("searching wiki...")
		return False

def wiki(input_word):
	url = "https://ja.wikipedia.org/wiki/" + input_word
	try:
		b.get(url)
		content = b.find_element(By.CLASS_NAME, "mw-parser-output")
		p = content.find_element(By.TAG_NAME, "p")
		print(p.text)
	except:
		print("could not find.")

if google(input_word) is False:
	wiki(input_word)
```

それぞれを関数化して、google検索がうまくいかなかった場合はwikiで調べる。

wikiは`https://ja.wikipedia.org/wiki/{word}`のように指定する。

これでどうだ。

```zsh:Terminal
python main.py "CPU"

>> searching wiki...
CPU（シーピーユー、英: Central Processing Unit）、中央処理装置（ちゅうおうしょりそうち）または中央演算処理装置（ちゅうおうえんざんしょりそうち）は、コンピュータの主要な構成要素のひとつで、コンピュータ内の他の装置・回路の制御やデータの演算などを行う装置[1]。演算装置と制御装置を統合したもの[1]。コンピュータにおける中心的な処理装置（プロセッサ）[2]。
```

うむ、よろしい。

## コマンド化する

このプログラムをコマンドライン上で打ち込めばいいわけだが、 `python main.py`をわざわざ打つのは面倒なので`zsh`の`function`を使います。

どこのディレクトリからでも使えるために、 **実行ファイル(python)** と **実行されるファイル(main.py)** の絶対パスを調べてみる。

* `python`の環境
```zsh:Terminal
conda info -e

>> scraping  *  /Users/syoshika/opt/anaconda3/envs/scraping
```
実行ファイルにするには、`/bin/python`を付け加える。
**`/Users/syoshika/opt/anaconda3/envs/scraping/bin/python`**

* `main.py`
```zsh:Terminal
pwd

>> /Users/syoshika/DIY/ggl
```

**`/Users/sho/DIY/ggl/main.py`**

それぞれをfunctionに入れて定義する。
今回は`ggl`って名前で使えるようにする。

```zsh:~/.zshrc
function ggl() {
	/Users/sho/opt/anaconda3/envs/scraping/bin/python /Users/sho/DIY/ggl/main.py $1
}
```

保存してアクティベートして使ってみる。

```zsh:Terminal
ggl DRAM

>> Dynamic Random Access Memoryは、コンピュータなどに使用される半導体メモリによるRAMの1種で、チップ中に形成された小さなキャパシタに電荷を貯めることで情報を保持する記憶素子である。放置すると電荷が放電し情報が喪われるため、常にリフレッシュを必要とする。
```

```zsh:Terminal
ggl BPO

>> ビジネス・プロセス・アウトソーシングは、企業運営上の業務やビジネスプロセスを専門企業に外部委託することを指す。
```

いい感じ！

## 欠点

### ちょっと遅い
2 ~ 5秒くらいかかる。~~普通に調べたほうが早い~~

### 同音意義に対応不可

BPAでは、ビジネスプロセスオートメーションのほうがマイナーらしい。

```zsh:Terminal
ggl BPA

>> ビスフェノールA は化学式 (CH₃)₂C(C₆H₄OH)₂ の有機化合物である。
白色の固体であり、有機溶媒に溶けるが水には溶けにくい。
一般には粉体であり、粉塵爆発を起こすことがあるため扱いに関して注意が必要。
```

粉塵爆発は草。

### 精度が悪い

```zsh:Terminal
ggl ls

>> searching wiki...
LS
```

もうちょい欲しいよ。

# 感想

欠点が多くてネタ記事みたいになっちゃったけど、
ある程度は実用性がありそうって思いたい。

自分のプログラムはただhtmlをパースして返しているだけだけど、機械学習使って`chatGPT`みたいなの作れないかなぁ


# おまけ

コマンドの名前を何にしようか考えてて、`whatis`とかどうかなって思ったら既にあった。

https://atmarkit.itmedia.co.jp/ait/articles/1702/23/news014.html

```zsh:Terminal
whatis python

>> python3(1), python(1)    - an interpreted, interactive, object-oriented programming language
ipython(1)               - Tools for Interactive Computing in Python
...
...
```

`man -f`と同じ動作らしいので、大したコマンドではないけど。

# 参考

https://stackoverflow.com/questions/72421952/how-to-stop-selenium-from-printing-webdriver-manager-messages-in-python