Google検索結果をスクレイピングするため下記サイトを参考に下記コードを実行したのですが  
下記の疑問点が解決できないのでどなたか教えて下さい。

①下記エラーを修正する方法を知りたい。

```

    a = str(list[i]).strip('')
    IndexError: list index out of range
    
```

②titleとそのURLを取得する方法を知りたい。

**参考にしたサイト**  
<https://qiita.com/ShinKano/items/d4b95ed809bd80329880>

**コード**

```

    import requests
    from bs4 import BeautifulSoup
    
    with open('keys.csv') as csv_file:
        with open('result.csv','w') as f:
    
        for keys in csv_file:
            result = requests.get('https://www.google.com/search?q={}/'.format(keys))
            soup = BeautifulSoup(result.text, 'html.parser')
            list = soup.findAll(True, {'class' : 'BNeawe vvjwJb AP7Wnd'})
            for i in range(3):
                a = str(list[i]).strip('<div class="BNeawe vvjwJb AP7Wnd">')
                result_title = a.strip('</')
                keyword = keys.rstrip("\n")
                f.write('{0},{1}\n'.format(keyword, result_title))
    
```
CC BY-SA 4.0
2019-11-10T23:07:55.857
60393
2021-06-27T08:06:15.557
2020-05-04T10:46:54.337
32986
32946
question
python python3 web-scraping beautifulsoup
Google検索結果のスクレイピングができない。
初学者さんだと思うのですが、なるべくリファレンスを使ってみた方がいいです。  
pythonでseleniumを使ってスクレイピングをするのであれば、以下の逆引きリファレンスが日本語で便利です。（もちろん英語が出来るなら公式に当たるべきです。）  
<https://www.seleniumqref.com/api/webdriver_gyaku.html>  
また、htmlの構造に関しても多少の知識が必要なので、chromeのデベロッパーツールからhtmlの要素のパスを取得する方法を学んでください。あとはpyhtonの文法がわかっていればすぐ出来るでしょう。
CC BY-SA 4.0
2019-11-12T02:25:28.250
60433
2019-11-12T02:25:28.250
36577
60393
answer
第一に、listというビルトインキーワードに何かを代入するべきではありません。

さて、list[i]がlist index out of
rangeになったということは、指定したiの要素が存在せず、従ってリストの中身が空であるか、またはrange(3)なので、少なくともiが2の時の要素が存在しません。

存在しない理由としての可能性はいくつかあります。

  * 変数名listのサイズが3より小さい。
  * クラス名は一定ではない: BNeawe vvjwJb AP7Wnd というクラス名が動的に生成されているなら、これを指定してもその都度存在するとは限りません。
  * スクレイピングをブロックされた: Googleは不振な挙動を検出してIPをブロックします。

変数名listのサイズの問題を解決するには、range(3)を使ったループを

```

    for i, _ in enumerate(list):
    
```

のように変更します。

class名が動的に生成される問題を解決するためには、class名以外を用いて取得する必要があります。以下は、Google検索をしたあとで表示されたHTMLです:

```

    <div class="XXXXXX">
      <a href="https://example.com/" ping="/url?blahblah"><br>
        <h3 class="XXXXXX XXXXXX"><span>TITLE</span></h3>
        <div class="XXXXXX XXXXXX">
          <cite class="XXXXXX XXXXXX XXXXXX">example.com</cite>
        </div>
     </a>
     略
    </div>
    
```

この場合、特定の正規表現に合致するaタグ要素を取得するような方法を考えるか、bs4でa要素を全取得していらないものをフィルタリングするような方法を考えるほうが良さそうです。汚いやり方ですが、

```

    from bs4 import BeautifulSoup
        
    def extract_google_url(soup):
        for x in soup.find_all("a"):
            try:
                x["href"]
                assert x.find("span") is not None
                assert x.find("div") is not None
                assert x.find("h3") is not None
            except:
                continue
            yield x
            
    with open("./Downloads/test - Google Search.html") as f:
        data = f.read()
    
    soup = BeautifulSoup(data, "html.parser")    
    results = list(extract_google_url(soup))
    
```

のように実行するのがその例です。dataに格納されているのは、"test"というクエリでググった検索結果一覧ページのhtmlファイルです。

また、Googleは不振な挙動を発見するとそのIPをブロックします。正確には、"I'm not a robot"
captchaを表示するようになります。言い換えれば、スクレイピングを許可していません。  
<https://stackoverflow.com/questions/22657548/is-it-ok-to-scrape-data-from-
google-results>

どうしてもブロックされずにスクレイピングするなら、法的リスクが生じうることを考える必要があります。さらに、いくつかのテクニックが必要になる可能性があります:

  * headlessブラウザを用いてスクレイピングする。
  * captcha認証をbypassする方法を考える。
  * アクセスするごとにcookieやその他特定可能な情報を削除・変更する。
  * 複数のプロキシを使うことで複数IPでアクセスを切り替える。
  * スクレイピングの挙動を人間に似たものにするために、一定時間のスリープ、単位時間あたりの合計表示件数、などを考慮する。

なお、タイトルとURLをHTMLをパースして取得する具体的な仕組みは、BeautifulSoupのドキュメントを読むことをおすすめします。  
<https://www.crummy.com/software/BeautifulSoup/bs4/doc/>
CC BY-SA 4.0
2020-10-29T13:19:08.487
71600
2020-10-30T04:37:52.233
2020-10-30T04:37:52.233
60393
answer