ソースコード全体はここ(GitHub)でも見れます。
目次
はじめに
Googleの検索結果を大量にほしいと思っても、apiや既存のモジュールだとアクセス制限があったので、自分で汎用的なクラスを作ることにしました。
作成時の方針は以下の2つ。
- テキスト検索(普通の検索)と画像検索の両方に対応
- 何も考えずに使える
注意
こんなタイトルにしといてなんなのですが,アクセス制限を完全に突破することはできていません。一つ(もしくは数個程度)のキーワードで大量の検索結果を取得することはできますが,大量のキーワードの検索結果を数件ずつ取得するのには向いていません。使いすぎるとIPアドレスに一時的な制限がかかって検索結果を取得できなくなります。使用は自己責任でお願いします。
***** 追記(2019/05/07) *****
Splashというブラウザを使うことで,アクセス制限にかからずに何度でも検索できることを確認しました(確認したのは150クエリ程度)。以下のプログラムを少し変えるだけなので,興味ある方はお試しください。そのうち別で記事を出すと思います。
# 変更箇所
self.GOOGLE_SEARCH_URL = 'https://www.google.co.jp/search'
↓
self.GOOGLE_SEARCH_URL = 'http://localhost:8050/render.html?url=https://www.google.co.jp/search'
Splashのインストール方法・使い方参考
【Python】HeadlessChromeに代わるクローリング用ブラウザSplash
ソースコード
import json
from urllib import parse
import requests
from bs4 import BeautifulSoup
class Google:
def __init__(self):
self.GOOGLE_SEARCH_URL = 'https://www.google.co.jp/search'
self.session = requests.session()
self.session.headers.update({
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:57.0) Gecko/20100101 Firefox/57.0'})
def Search(self, keyword, type='text', maximum=100):
'''Google検索'''
print('Google', type.capitalize(), 'Search :', keyword)
result, total = [], 0
query = self.query_gen(keyword, type)
while True:
# 検索
html = self.session.get(next(query)).text
links = self.get_links(html, type)
# 検索結果の追加
if not len(links):
print('-> No more links')
break
elif len(links) > maximum - total:
result += links[:maximum - total]
break
else:
result += links
total += len(links)
print('-> Finally got', str(len(result)), 'links')
return result
def query_gen(self, keyword, type):
'''検索クエリジェネレータ'''
page = 0
while True:
if type == 'text':
params = parse.urlencode({
'q': keyword,
'num': '100',
'filter': '0',
'start': str(page * 100)})
elif type == 'image':
params = parse.urlencode({
'q': keyword,
'tbm': 'isch',
'filter': '0',
'ijn': str(page)})
yield self.GOOGLE_SEARCH_URL + '?' + params
page += 1
def get_links(self, html, type):
'''リンク取得'''
soup = BeautifulSoup(html, 'lxml')
if type == 'text':
elements = soup.select('.rc > .r > a')
links = [e['href'] for e in elements]
elif type == 'image':
elements = soup.select('.rg_meta.notranslate')
jsons = [json.loads(e.get_text()) for e in elements]
links = [js['ou'] for js in jsons]
return links
使い方
「ドラえもん」の検索結果が200件ほしいなら、こんな感じで使います。resultにはurlのリストが渡ります。これなら何も考えずに使えるかな?
google = Google()
# テキスト検索
result = google.Search('ドラえもん', type='text', maximum=200)
# 画像検索
result = google.Search('ドラえもん', type='image', maximum=200)