見出し画像

【Python】検索サイトの「次のページ」のURLを取得する実例

こんばんは。自立に向けてとにかく手をうごかしたいとっとです。

今日は、GoogleとYahooで任意のワード検索をして得られたページで、次のページに行くためのURLを取得するやり方について、わたしなりの実例をまとめてみたいとおもいます。


以下の記事で触れているSeleniumによるブラウザ操作では、URL情報を取得するのではなくクリックしたいボタン情報をXPathとして取得していましたが、今回はURL情報を取得するためにHTMLの解析が必要となりました。


いろいろなサイトを参考にしましたが、サンプルコード結果はあっても、具体的にどのようにbeautifulsoupのSelect(またはFind)の引数を指定すれば所望の部分を拾えるのか、いまいち理解できずにいました。

抽出元となるHTMLテキスト + コードサンプル + 結果

が1セットになって紹介しているサイトをあまり見かけなかったため、わたしのやった実例をまとめてみます。


ここでやりたいこと

Googleのサイトで、例えば”test”というワードで検索し、

画像1

出てきた結果画面の、”次へ”のリンクを取得したいです。

画像2


この”次へ”のリンクを取得するには、beautifulsoupでどのように指定すればよいのでしょうか。


解析手順実例(googleの場合)

まず、何はともあれ検索結果のページを取得します。

#Googleの場合
 url = 'https://www.google.co.jp' + '/search?' + 'hl=ja' + '&num=10' + '&q=' + 'test'
 res = requests.get(url)

#res.textは、検索結果のページのHTML
 bs4_res = bs4.BeautifulSoup(res.text, 'lxml')

これで、googleでtestというワードで検索した最初のページがbs4_resに格納されます。

bs4_resをprintしてみました。

<!DOCTYPE html>
<html lang="ja"><head><meta charset="utf-8"/><meta content="/images/branding/googleg/1x/googleg_standard_color_128dp.png" itemprop="image"/><title>test - Google 検索</title><script nonce="wmldDvWcJv60lECFZIquKA==">(function(){
document.documentElement.addEventListener("submit",function(b){var a;if(a=b.target){var c=a.getAttribute("data-submitfalse");a="1"===c||"q"===c&&!a.elements.q.value?!0:!1}else a=!1;a&&(b.preventDefault(),b.stopPropagation())},!0);document.documentElement.addEventListener("click",function(b){var a;a:{for(a=b.target;a&&a!==document.documentElement;a=a.parentElement)if("A"===a.tagName){a="1"===a.getAttribute("data-nohref");break a}a=!1}a&&b.preventDefault()},!0);}).call(this);(function(){
var a=window.performance;window.start=Date.now();a:{var b=window;if(a){var c=a.timing;if(c){var d=c.navigationStart,f=c.responseStart;if(f>d&&f<=window.start){window.start=f;b.wsrt=f-d;break a}}a.now&&(b.wsrt=Math.floor(a.now()))}}window.google=window.google||{};var h=function(g){g&&g.target.setAttribute("data-iml",Date.now())};document.documentElement.addEventListener("load",h,!0);google.rglh=function(){document.documentElement.removeEventListener("load",h,!0)};}).call(this);(function(){window.google.erd={sp:'srp',jsr:0,bv:81};})();(function(){
var c=[],e=0;window.ping=function(b){-1==b.indexOf("&zx")&&(b+="&zx="+Date.now());var a=new Image,d=e++;c[d]=a;a.onerror=a.onload=a.onabort=function(){delete c[d]};a.src=b};}).call(this);</script><style>body{margin:0 auto;max-width:736px;padding:0 8px;}a{color:#1967D2;text-decoration:none;tap-highlight-color:rgba(0,0,0,.10)}a:visited{color:#4B11A8}a:hover{text-decoration:underline}img{border:0}html{font-family:Roboto,Helvetica Neue,Arial,sans-serif;font-size:14px;line-height:20px;text-size-adjust:100%;color:#3c4043;word-wrap:break-word;background-color:#fff}.bRsWnc{background-color:#fff;border-top:1px solid 
・・・・以下略


はい、見る気になりません。

みづらいのは、HTMLのタグ構成が連続し、テキストでならんじゃってるからですが、以下のようなサイトでタグ構成をもとに成形してくれます。


ここでは以下略としていますが、いずれにせよ略した中のどこかに、”次へ”のリンクがあるはずです。

そこで、printしたbs4_resの中身をメモ帳に貼り付けて、”次へ”で検索してみたところ、以下の箇所が次のページに行くリンクであることが分かりました。

<a aria-label="次のページ" class="nBDE1b G5eFlf" href="/search?q=test&amp;hl=ja&amp;ie=UTF-8&amp;ei=J1Y_YeLpMsLA0PEPpNifwAo&amp;start=10&amp;sa=N">次へ &gt;</a>


なるほど、class"nBDE1b G5eFlf"というらしいです。

一応このクラス名の文字列を検索してみたら、このページには一つしか該当がなかったため、このクラス名でfindすることにしました。

url_next = bs4_res.find(class_ = 'nBDE1b G5eFlf').get('href')


url_nextをprintしてみます。

/search?q=test&hl=ja&ie=UTF-8&ei=P6FAYce5HNmztQbu4ZewCg&start=10&sa=N

ちゃんと次へのリンクを取得できています。ただし、頭にベースとなる'https://www.google.co.jp'を足してやらないとURLとして機能しないので、そこを文字列として足してやって、うまくいきました。


解析手順実例(Yahooの場合)

次に、Yahooでの実例です。

まずはYahooで”test”を検索。

#Yahooの場合
 url = 'http://search.yahoo.co.jp' + '/search?' + 'p=' + 'test'
 res = requests.get(url)
 
#res.textは、検索結果のページのHTML
 bs4_res = bs4.BeautifulSoup(res.text, 'lxml')

ちなみにYahooのURLパラメータ規則について解説しているサイトは見つけきれませんでした。なので、私はp=検索ワードしかつかめていません。

こちらもbs4_resをprintしてメモ帳に貼り付け、次へで検索してみると、以下の箇所が該当のようです。

<a data-ylk="rsec:pagination;slk:next;pos:1" href="https://search.yahoo.co.jp/search?p=%E6%96%B0%E5%B9%B9%E7%B7%9A&amp;ei=UTF-8&amp;b=11">次へ »</a>


・・・ん?classの指定が無い。。試練です。(わたしの中で)

beautifulsoupでHTMLを解析する場合、select または findの関数の引数に検索条件を入れて抽出しますが、わたしが調べたところ条件にできるのは、

タグそのものを指定するか、classを指定するか、textを指定するか、

だったので、この該当箇所からどうやってリンクを取得すればいいのか、わかりませんでした。

タグ’a’なので複数あるし、class無いし。


一瞬、順番に親タグから追って指定していくのも考えましたが、人力でHTMLページ全体のタグ構成を分析するのは大変そうなので、もうあとは、textで指定するしかないと思い、以下のように抽出しました。

pickup_tag_a = bs4_res.select('a')
     
for txt in pickup_tag_a:
    if '次へ' in txt.text:
    url_next = txt.get('href')

まずは、bs4_resのページ全体から、aタグ部分だけをピックアップして対象を減らします。

次に、ピックアップしたaタグのリストを上から順に見ていき、テキスト部分が”次へ”という文字列なら、そのaタグのリンク先を取得します。

結果をprintしてみます。

https://search.yahoo.co.jp/search?p=test&ei=UTF-8&b=11

うまくいきました。


まとめ

beautifulsoupで抽出する場合は、seleniumを使ってブラウザ操作しながら情報を抽出していく場合に比べて、HTMLタグ構成をある程度自分で見る必要があることが分かりました。

その分、と言っていいのかわかりませんが、beautifulsoupで抽出するとブラウザを動かさない分、動作がすっきりします。

サーバ負荷とならないよう配慮しながら、今後もスクレイピングを楽しみたいと思います。

最後までご覧いただき、ありがとうございました。



この記事が気に入ったらサポートをしてみませんか?