今回の内容
内容に一部不具合がありましたので修正しています。再確認お願い致します。
コピペでスクレイピング② クラウドワークスの新着情報を収集に続き、今回は取得したページソースでBeautifulsoupを利用して、必要なデータの抜き出しを行いたいと思います。
ブラウザを開き、目的のページを開いた状態で『F12』ボタンを押すとそのページのソースコードを見入ることができる。というところまでが、前回の内容でした。
ちなみに、このソースコードを見る画面を『デベロッパーツール』といいます。
では、要素を取り出してみます。
要素の探し方
デベロッパーツールの上部左端の赤枠で囲った部分に図のような記号があると思います。
ソコをクリックしてください。
次に、取得したい要素、ここで言うと赤枠の部分をクリックします。
そうすると、ソースコードに選択された部分が表示されます。
選択された部分の左上に『・・・』という記号が現れますのでそこをクリック
メニューが出ますので、『コピー』→ 『selectorをコピー』をクリックします。
クリップボードには以下のタグがコピーされます。
『 #result_jobs > div.search_results > ul > li:nth-child(1) > div > div > div.item_body.job_data_body > div.job_data_row > div.job_data_column.summary > h3 > a 』
これをひとまず、メモ帳に貼り付けておきます。
今度は2列目のタイトルを同じように繰り返して、コピーされたタグをメモ帳に貼り付けます。
1回目と2回目のコピーを比較します。
【1回目コピー】
『#result_jobs > div.search_results > ul > li:nth-child(1) > div > div > div.item_body.job_data_body > div.job_data_row > div.job_data_column.summary > h3 > a』
【2回目コピー】
『#result_jobs > div.search_results > ul > li:nth-child(2) > div > div > div.item_body.job_data_body > div.job_data_row > div.job_data_column.summary > h3 > a』
よく見ると、1回目が『li:nth-child(1) 』になっているのに、2回目は『li:nth-child(2) 』になっている部分があります。他は差異が無いようです。
ブラウザに画面が表示される時、ブラウザはこのhtmlの差を見分けて表示する順序を変えているのです。
今回は一挙に表示一覧を取得するので、この数字があるとひとつずつしかデータが取得されなくなるので、
この違いの部分を変更します。
【変更後】
『 #result_jobs > div.search_results > ul > li > div > div > div.item_body.job_data_body > div.job_data_row > div.job_data_column.summary > h3 > a 』
としました。
『:nth-child』の部分も削除してるんじゃ?と思った方
理由は2つあります。Beautifulsoupは『:nth-child 』という表記を使うとエラーが出てしまうという点がひとつ、もう一つはhtmlを知ってる人は解ると思いますが、『li』というタグさえ書いておけば用途が足りてしまうということもあります。
全体のコードを表記しますので、よくわからない方は無視して、そのままコピーしてもらえば良いと思います。
タグのデータを取得する
《修正》
この後に出てくるループ処理を行った場合、seleniumのセッションが切れない不具合がありましたので部分的に修正しました。コード内に修正、追記部分を加筆していますので再確認お願いします。
# 追記:見やすくなるように加筆
from bs4 import BeautifulSoup
import lxml
import selenium_tool as st
import os
# 追記:見やすくなるように加筆
keyword = 'スクレイピング'
target_url = f'https://crowdworks.jp/public/jobs/search?keep_search_criteria=' \
f'true&order=score&hide_expired=false&search[keywords]={keyword}'
main_url = 'https://www.crowdworks.jp'
# def new_data_get(soup): # 修正前
def new_data_get(target_url): # 修正後
# 追記部分===========================
res = st.source_code_get(target_url)
soup = BeautifulSoup(res, "lxml")
# 追記部分ここまで===================
# 1
title_tags = soup.select(
'#result_jobs > div.search_results > ul > li > div > div >'
' div.item_body.job_data_body > div.job_data_row > div.job_data_column.summary > h3 > a')
list_datas = []
for title_tag in title_tags:
# 2 タイトル取得
item_name = title_tag.text
# 3 URL取得
item_url = main_url+title_tag.get('href')
# 4 urlの末尾の番号がユニークなのでIDとして取得
item_id = item_url.split('/')[-1]
# 5 データをまとめる
list_datas.append([item_id, item_name, item_url])
return list_datas
必要なデータはタイトルとメインページへのURLリンクだけなので、
実際に取得する部分は短めです
#1
先程修正したselectorの内容がここに来ます。
複数行のタイトルを一挙に取得するのでリスト化されてtitle_tagsに格納されます。
因みに取得したデータはこのようなデータになります。
aというタグの中に、リンクとタイトルが内包されています。
これをBeautifulsooupで取り出すわけです。
部分的にはこのような内容が取得されています。
1件分を抜き出すとこのような感じです。
<a data-item-title-link="" href="/public/jobs/8144592" rel="noopener noreferrer" target="_blank">ヤフオク特定商品の価格取得</a>
この1件分のデータから必要部分を抜き出し、件名とURLに分離します。
for文でデータを抜き出してゆく
#2 item_name変数に案件のタイトルを格納
item_name = title_tag.text
#3 URLを抜き出し
URLを抜き出しているのですが、
href="/public/jobs/8144592
となっており、途中からしかURLがありません、ですのでmain_url変数に格納した頭の部分と結合します。
item_url = main_url+title_tag.get('href')
ついでに、新着データを簡単に比較できるように、案件のIDのようなものを取得します。
案件のURLを見ると、末尾に数字が並んでおりこれが一意の数字のようです。
これをIDとして取り込んでおきましょう。
item_urlで取得したデータをsplit関数で『/』部分で分割して、一番最後の要素を取得すれば数字だけ抜き取れます。
item_id = item_url.split('/')[-1]
#5 後は扱いやすいように『 list_datas 』にまとめて格納しておきます。
データの取得は以上です。
次回は前のデータとの差分を抽出します。