- 更新日: 2022年07月26日
- 公開日: 2018年08月02日
【実用的】スクレイピング・データをWebサイトに応用
人工知能にブロックチェーンに、データ解析と業務・私用関係なくPythonに触れる機会が多い昨今。
今までWordPressや他のブログエンジンでメディア運営されていた方の中には、「WebでPython使えた方が学習効率よくない?」と思われる方もいらっしゃるのでは。
そこで今回は、Pythonの学習事例で多い「スクレイピング」で取得するデータをWebページに反映させる、ということを行ってみます。
【実用的】スクレイピング・データをWebサイトに応用
今回試す内容
今回は、サンプルのプロフィールページに、フリーランス仲介サイトで公開されている実績数などを引用してみます。
仲介サイトで表示されるデータを自分のプロフサイトに反映できますので、仕事の実績がライブで反映。
これでイチイチ自分のプロフィール・データ更新を気にしなくても、仕事に集中するだけで数字が伸びます。
そしてまたそれを見たクライアントの方から仕事のオファーをもらえるかもしれません。
いい循環が生まれそうですね。
準備
- Jupyter Notebook
- テキストエディタ
- bottle.py
PythonコードをWebブラウザで手っ取り早く実行させようと思うと「Bottle」というWebフレームワークが便利です。 フレームワークというと初期設定や内容理解に時間が、、、と思われるかもしれませんが、今回は bottle.py と index.html、 スクレイピング用Pythonファイルの 3つのみ使います。
Jupyter Notebook は、Webスクレイピングしていく中で最終抜き取りたいデータまでのプログラム加工に便利なため、使用します。
スクレイピング・ターゲットの選定
今回は、Webスクレイピングで有名な「Beautiful Soup4」を使って作業していきます。
データ引用したいターゲットサイトは以下の通りにしました。
- Lancers(ランサーズ)
- CrowdWorks(クラウドワークス)
- Shufti(シュフティ)
まずWebスクレイピングがブロックされていないか確認してみます。
【ランサーズ 自分のアカウント】
import requests
url = requests.get('https://www.lancers.jp/profile/oshima_masara')
url
【クラウドワークス 自分のアカウント】
url = requests.get('https://crowdworks.jp/public/employees/14218')
url
【シュフティ トップユーザー】
url = requests.get('https://www.shufti.jp/users/profile/113910/contract')
url
シュフティ新規アカウント作成するも、データ反映されないためトップユーザーの Y.Matsuzaki_fortyoneさんのプロフィールを参考にさせて頂きました。ご了承ください。
<< 実行結果 >>
なんとランサーズは 403 の読み込みエラー。
403:アクセスしたページはインターネット上に存在するが、閲覧することが許可されていません。
あとの2件は読み込み可能なので、クラウドワークスとシュフティの2つからプロフィールデータを引用してみます。
尚、3件とも現段階(2018.07.25)ではAPI公開されていませんでした。
クラウドワークスのデータをスクレイピング
クラウドワークスの自分の実績をスクレイピングしてみます。
まずは自分のプロフィールページ https://crowdworks.jp/public/employees/14218 にアクセスして、実績数の CSS を確認。
span.score contracts
とスクレイピングに適した CSS です。
それでは Beautiful Soup の雛形に上記要素をあてはめてみます。
import requests, bs4
res = requests.get('https://crowdworks.jp/public/employees/14218')
soup = bs4.BeautifulSoup(res.text, "html.parser")
elems = soup.select('span.score.contracts')
elems
<< 実行結果 >>
今回は、実績数だけ欲しいので getText()
関数を使ってデータ整形。
いいですね、クラウドワークス上の実績数と同じ "10" を引用できています。
せっかくなので評価も引用。
import requests, bs4
res = requests.get('https://crowdworks.jp/public/employees/14218')
soup = bs4.BeautifulSoup(res.text, "html.parser")
elems = soup.select('span.score.feedbacks')
for elem in elems:
out = elem.getText()
out
<< 実行結果 >>
欲しいデータを引用できたので、一旦ここで Webページに表示される作業をしてみます。
スクレイピングしたデータをHTMLファイル内で読み込み
Pythonでスクレイピングしたデータを変数化して、それを Bottle の書式にあてはめることでスクレイピングしたデータをWeb上に表示できます。
【編集するファイル】
- scraping.py
- index.html
解説の仕方は色々ありますが、とりあえず答えから。
scraping.py
from bottle import route, run, template, redirect, request
from requests import get
from bs4 import BeautifulSoup
@route("/")
def index():
number1 = get_number1()
number2 = get_number2()
return template("index", out1=number1, out2=number2)
def get_number1():
url = 'https://crowdworks.jp/public/employees/14218'
response = get(url)
soup = BeautifulSoup(response.text, "html.parser")
elems = soup.select('span.score.contracts')
for elem in elems:
out1 = elem.getText()
return out1
def get_number2():
url = 'https://crowdworks.jp/public/employees/14218'
response = get(url)
soup = BeautifulSoup(response.text, "html.parser")
elems = soup.select('span.score.feedbacks')
for elem in elems:
out2 = elem.getText()
return out2
run(host="localhost", port=1029, debug=True, reloader=True)
index.html
<!DOCTYPE html>
<html lang="jp">
<head>
<meta charset="UTF-8">
<title>フリーランス向けプロフページのサンプル(Python3 + Bottle)</title>
</head>
<body>
<hr>
<hr>
<p style="font-size:2em">クラウドワークス受注件数: {{out1}} 件</p>
<p style="font-size:2em">クラウドワークス評価: {{out2}}</p>
<a href="https://crowdworks.jp/public/employees/14218" target="_blank">わたしの実績</a>
<hr>
<hr>
</body>
</html>
ディレクトリ構成
<< 実行結果 >>
こちらはターミナルもしくはコマンドプロンプトから以下のコードを実行。
python scraping.py
そして指定したローカルホスト http://localhost:1029 にアクセスします。
解説
まず scraping.py
の方では、『クラウドワークスのデータをスクレイピング』の章でご紹介したコードを get_number1()
と get_number2()
にモジュール化。
そしてそれを index()
関数内の number1
と number2
という変数に代入。
最後に template()
関数に number1
と number2
を out1
、 out2
に変数化して出力。
出力先は、最終行の run()
関数で制御。
次に index.html
側。
こちらは {{out1}}
、 {{out2}}
とダブル波カッコで先ほどの out1
、 out2
を囲むと出力。
ちょっと見た目が寂しいので、上記の index.html
のようにコード編集しています。
シュフティのデータをスクレイピング
同じ要領で シュフティ のデータもスクレイピングしたいと思います。
シュフティは自分のアカウントがリストアップされていないため、トップユーザーの Y.Matsuzaki_fortyone さんを参考にさせて頂きました。
それでクラウドワークスと同じ要領で作業しようと思った矢先、なんと欲しいデータのCSS構造が他のデータと一緒。つまりデータを特定できないんですね。
そこでシュフティの場合は、段階的にコードを絞って、最終的なデータ抽出に結び付けたいと考えました。
ステップ1
まずWebページの抽出方法を、response.text, "html.parser"
から page.content, "lxml"
に変えます。
理由は、CSSコードではなくHTMLコードで取得したいデータまでたどり着きたいからです。
import requests
from bs4 import BeautifulSoup
page = requests.get('https://www.shufti.jp/users/profile/113910/contract')
soup = BeautifulSoup(page.content, "lxml")
soup
<< 実行結果 >>
ステップ2
次に欲しいデータ(納品実績)の周辺HTMLコードを見ていくと、リストタグの <ul>
に納まっていることが確認できます。
Beautiful Soupの find()
関数を使って、<ul>
コードを抽出できるか確認してみます。
import requests
from bs4 import BeautifulSoup
page = requests.get('https://www.shufti.jp/users/profile/113910/contract')
soup = BeautifulSoup(page.content, "lxml")
box = soup.find('ul' ,'stripe_list')
box
<< 実行結果 >>
ちょっと欲しいデータに近づけた気がします。
ステップ3
欲しいデータは、<li>
タグ内に入っていますので、<li>
タグのみの表示結果になるようにもう一段階絞り込みを行います。
import requests
from bs4 import BeautifulSoup
page = requests.get('https://www.shufti.jp/users/profile/113910/contract')
soup = BeautifulSoup(page.content, "lxml")
box = soup.find('ul' ,'stripe_list')
box_1 = box.findAll('li')
box_1
<< 実行結果 >>
ステップ4
一番簡単な方法で作業を進めます。
ステップ3の出力結果をよく見てみると、データ形式はリスト構造です。出力データが []
で囲まれていますよね。
このリスト構造の特徴を活かして、欲しいデータの順位を確認。
3番目ですね、コードに書いてみます。
import requests
from bs4 import BeautifulSoup
page = requests.get('https://www.shufti.jp/users/profile/113910/contract')
soup = BeautifulSoup(page.content, "lxml")
box = soup.find('ul' ,'stripe_list')
box_1 = box.findAll('li')
work_count = box_1[2]
work_count
<< 実行結果 >>
おお、だいぶ目的のデータまで近づけたように思います。
ステップ5
次に <li>
とか <strong>
とかいらないので、 getText()
関数でテキストのみの表示に変換。
import requests
from bs4 import BeautifulSoup
page = requests.get('https://www.shufti.jp/users/profile/113910/contract')
soup = BeautifulSoup(page.content, "lxml")
box = soup.find('ul' ,'stripe_list')
box_1 = box.findAll('li')
work_count = box_1[2]
work_count_2 = work_count.getText()
work_count_2
<< 実行結果 >>
ステップ6
最後に数字だけ取得するために、、、今回はリスト機能を使いました。
import requests
from bs4 import BeautifulSoup
page = requests.get('https://www.shufti.jp/users/profile/113910/contract')
soup = BeautifulSoup(page.content, "lxml")
box = soup.find('ul' ,'stripe_list')
box_1 = box.findAll('li')
work_count = box_1[2]
work_count_2 = work_count.getText()
out3 = work_count_2[1:4]
out3
<< 実行結果 >>
最終的なコード
シュフティの納品実績も抽出出来ましたので、こちらに最終的なコードをご紹介。
scraping.py
from bottle import route, run, template, redirect, request
from requests import get
import requests
from bs4 import BeautifulSoup
@route("/")
def index():
number1 = get_number1()
number2 = get_number2()
number3 = get_number3()
return template("index", out1=number1, out2=number2, out3=number3)
def get_number1():
url = 'https://crowdworks.jp/public/employees/14218'
response = get(url)
soup = BeautifulSoup(response.text, "html.parser")
elems = soup.select('span.score.contracts')
for elem in elems:
out1 = elem.getText()
return out1
def get_number2():
url = 'https://crowdworks.jp/public/employees/14218'
response = get(url)
soup = BeautifulSoup(response.text, "html.parser")
elems = soup.select('span.score.feedbacks')
for elem in elems:
out2 = elem.getText()
return out2
def get_number3():
page = requests.get('https://www.shufti.jp/users/profile/113910/contract')
soup = BeautifulSoup(page.content, "lxml")
box = soup.find('ul' ,'stripe_list')
box_1 = box.findAll('li')
work_count = box_1[2]
work_count_2 = work_count.getText()
out3 = work_count_2[1:4]
return out3
run(host="localhost", port=1055, debug=True, reloader=True)
index.html
<!DOCTYPE html>
<html lang="jp">
<head>
<meta charset="UTF-8">
<title>フリーランス向けプロフページのサンプル(Python3 + Bottle)</title>
</head>
<body>
<hr>
<hr>
<p style="font-size:2em">クラウドワークス受注件数: {{out1}} 件</p>
<p style="font-size:2em">クラウドワークス評価: {{out2}}</p>
<a href="https://crowdworks.jp/public/employees/14218" target="_blank">わたしの実績</a>
<hr>
<hr>
<p style="font-size:2em">Shufti納品実績: {{out3}}</p>
<a href="https://www.shufti.jp/users/profile/113910/contract" target="_blank">Y.Matsuzaki_fortyoneさんの実績引用</a>
<br>
<hr>
<hr>
</body>
</html>
<< 実行結果 >>
python scraping.py
\AIエンジニアに必要なスキルが身に付く/
まとめ
今回フリーランスの実績を自動的に更新できるWebページを作ってみましたが、手間に感じましたでしょうか?
私自身シュフティの実績数引用は、サンプルコードもなくできるかな?と思いましたが、一つ一つコードを分解し、Pythonの基本機能を思い出しながら進めてみると、スクレイピングに成功しました。恐らくシュフティのスクレイピングは、正規表現でも難しく、今回のやり方が簡単でよかったように思います。楽しかったです。
Pythonの基礎を理解していればこうしたスクレイピングの場面をはじめ、色々なところで応用が効きますので、”基礎”早い段階で習得しておきたいですね。
CodeCampなら忙しくても、遠方でもオンラインなので大丈夫です。またマンツーマン方式を採用していますので、周りを気にせず聞きたいことを聞けます。Pythonの基礎、身につけてみませんか?
- この記事を書いた人
- オシママサラ