はじめに
pythonを学ぶからにはスクレイピングをしてみたい…
そこで、今日のニュースとSteamの人気ゲームtop5をスクレイピングして表示するbotを作成。
ついでに、botでOCRして欲しいとの依頼があったりなかったりしたので、そちらも作成。
環境
- Windows10 64bit
- python3
スクレイピング
作ったbot
- Steam人気ゲーム教えてbot
- 主要のニュース教えてbot
Slackbotの作成方法
は以前に書いたこちらの記事をご覧ください。
Beautiful Soupのインストール
下記のコマンドを開発環境内でインストール
pip install beautifulsoup4
要素の取得方法
基本的には、開発者モード(F12)を使って要素を抽出します。
- steamの場合
赤い四角で囲った部分のElementsが
<span class="title"></span>
とわかります。
- yahooニュースの場合
赤い四角で囲った部分は基本的に以下のようなElementsになっていることがわかりました。
<ur class="topics">
<li class="topTpi">
<div>
<h1 class="ttl">
<a href=…></a>
</h1>
</div>
</li>
<li class="topTpi">
<div>
<p class="ttl">
<a href=…></a>
</p>
</div>
</li>
…以下省略
</ur>
コード
- Steam人気ゲーム教えてbot
@respond_to('Steamで人気のゲーム教えて')
def steam_reply(message):
import urllib.request, urllib.error
from bs4 import BeautifulSoup
#Steamから人気のゲーム情報をスクレイピング
url = 'http://store.steampowered.com/search/?filter=topsellers&os=win'
html = urllib.request.urlopen(url)
soup = BeautifulSoup(html, "html.parser")
#span要素を取得
span_tag = soup.select('.title')
#ループをまわして配列にいれる
for i in range(5):
span_tag[i]
#要素の文字列を取得
span = span_tag[i].string
messa = str(i+1) + '位' + span
message.reply(messa)
- 主要のニュース教えてbot
@respond_to('主要のニュースを教えて')
def news_reply(message):
import urllib.request, urllib.error
from bs4 import BeautifulSoup
#yahooニュースをスクレイピング
url = 'https://news.yahoo.co.jp/'
html = urllib.request.urlopen(url)
soup = BeautifulSoup(html, "html.parser")
#a要素を取得
a_tag = soup.find('ul', attrs={'class' : 'topics'})
tags = a_tag.find_all(attrs ={'class' : 'ttl'})
for title in tags:
message.reply(title.find('a').contents[0])
コード解説
Steambotの方は、span要素からclassが"title"のものを抽出しました。
詳しい要素の取り方はこちらを参考にしました。
この取り方一覧を参考にすれば無敵な気がします。
OCR
作ったbot
おやおや
精度はあまりよくないかもしれないです。
ツールをインストール
tesseract-ocr-setup-3.02.02.exeをインストール
pythonにインポートさせるため、以下2つのコマンドを実行。
pip install pyocr
pip install Pillow
プログラムの流れ
OCRを行う際に、どうしても自分のローカルフォルダに画像を保存する必要があったため、
Slackに画像をUP → ローカルフォルダ内に画像を保存 → OCR → 結果をSlackに投稿
という順序を取っています。
コード
"トークン"の部分ではSlackbotで取得したトークンを入力します。
Slackbot_Settings.pyで記載したものと同じです。
詳しくはここのAPItoken部分を参照。
@listen_to('(.*)')
def testo_func(message, params):
from PIL import Image
import sys
import pyocr
import pyocr.builders
import requests
import shutil
tools = pyocr.get_available_tools()
if len(tools) == 0:
message.reply('OCRツールないよ')
else:
if 'file' in message.body:
url = message.body['file']['url_private']
flag = message.body['file']['filetype']
tmpfile = './tmp.' + flag
token = 'トークン'
res = requests.get(url, headers={'Authorization': 'Bearer %s' % token}, stream=True)
#ファイル書き込み
with open(tmpfile, 'wb') as fp:
res.raw.decode_content = True
shutil.copyfileobj(res.raw,fp)
#ここからOCRの処理
tool = tools[0]
langs = tool.get_available_languages()
lang = langs[0]
im1 = Image.open('tmp.png')
txt = tool.image_to_string(
im1,
lang=lang,
builder=pyocr.builders.TextBuilder(tesseract_layout=6)
)
message.reply(txt)
コード解説
まず、画像ダウンロード部分。画像の保存にはrequestsを使うらしいです。
url,flgで設定している値(message.body[~][~]部分)はSlackのfiletypeを見て頂ければと。
ファイル書き込み部分に関してはこちらのサイトを見て作成しました。
続いてOCR部分。
txt部分でおもにOCRの対象や言語、オプションの設定をしてます。
引数は画像(実行するディレクトリからの相対パスor絶対パス)、翻訳したい言語、OCRをする際のオプションです。
さいごに
このbotを作ってから時間がたってしまいました。
うろ覚えな部分があるので、もう一回復習して解説を充実させたいと思います。