[機械学習で推奨タグ付け #3] 学習要素のスクレイピング


Hi, it's Sunday but little tired - :(

So this is next step for my project - "Learning from tagged web site". I already have bookmarked date on social bookmark service. Learning tags from the data for suggesting tag for another web site.

So actually today's script is only for specific site to getting necessary data. However I think it's good exercise for using BeautifulSoup. Let's start.

What data I have to collect for learning? - Web sites I checked and its tags. So I scrape web link data and tags on Hatena bookmark which is social bookmark service site Here is my bookmark page.. Check HTML source code, it's using JavaScript and I can't see date from ordinal HTML source. however there is JS off site. I confirmed there are necessary data I want. Below is html tag for one bookmark. I's long but please check but take it easy.

<li class="entrylist-unit"
data-eid="272036974"
data-bookmark-count="1"
>
<h3 class="entry entry-title" id="bookmark-272036974" style="background-image:url(http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Fqiita.com%2F)">
<a href="http://qiita.com/Bython-Chogo/items/28475b95e48f76dbc00a" target="_blank" class="entry-link" data-track-click-target="direct">MachineLearning - [機械学習で推奨タグ付け #2] スクレイピングスクリプトの拡張 - Qiita</a> <img src="/images/camera.gif" alt="このエントリーには写真が掲載されています" title="このエントリーには写真が掲載されています" />
<a class="domain" href="/bython-chogo/?url=http%3A%2F%2Fqiita.com%2F" rel="nofollow">qiita.com</a>
</h3>
<ul>

<li class="category"><a href="/hotentry/it" class="category group2">テクノロジー</a></li>

<li class="users"><a href="/entry/qiita.com/Bython-Chogo/items/28475b95e48f76dbc00a" data-track-click-target="entry" title="はてなブックマーク - MachineLearning - [機械学習で推奨タグ付け #2] スクレイピングスクリプトの拡張 - Qiita (1ブックマーク)"><span>1</span> user</a></li>

<img src="http://cdn-ak.b.st-hatena.com/images/keyword.gif?7c8c9ecc9d409bd521163fab85c5da611beba276" alt="キーワード" title="このページに含まれるキーワード" />
<ul class="keywords">

<li class="keyword"><a href="http://d.hatena.ne.jp/keyword/scraper">scraper</a></li>

<li class="keyword"><a href="http://d.hatena.ne.jp/keyword/tag">tag</a></li>

<li class="keyword"><a href="http://d.hatena.ne.jp/keyword/Qiita">Qiita</a></li>

<li class="keyword"><a href="http://d.hatena.ne.jp/keyword/SCRIPT">SCRIPT</a></li>

<li class="keyword"><a href="http://d.hatena.ne.jp/keyword/blog">blog</a></li>

<li class="keyword"><a href="http://d.hatena.ne.jp/keyword/Hatena%20Blog">Hatena Blog</a></li>

<li class="keyword"><a href="http://d.hatena.ne.jp/keyword/encode">encode</a></li>

</ul>

</ul>

<div class="curvebox-header"><div></div></div>
<div class="curvebox-body comment">
<ul class="comment ">

<li data-user="bython-chogo" onmouseover="Hatena.Bookmark.CommentEditor.Hover.create(this, 'http://qiita.com/Bython-Chogo/items/28475b95e48f76dbc00a');" class="mine">    <a href="/bython-chogo/"><img src="http://cdn1.www.st-hatena.com/users/by/bython-chogo/profile_s.gif" class="profile-image" alt="bython-chogo" title="bython-chogo" width="16" height="16" /></a>
<a class="username" href="/bython-chogo/20151126#bookmark-272036974">bython-chogo</a>    <img style='display:none' id="delete-272036974" src="http://cdn-ak.b.st-hatena.com/images/delete.gif" alt="ブックマークを削除する" title="ブックマークを削除する" class="inplace-delete-icon" />
<img src="http://cdn-ak.b.st-hatena.com/images/edit.gif" alt="コメントを編集する" title="コメントを編集する" style="display:none" class="inplace-edit-icon" />
<span class="tags"><a rel="tag" class="user-tag" href="/bython-chogo/%E3%82%BB%E3%83%AB%E3%82%AF%E3%83%9E/">セルクマ</a></span>
<span class="comment"></span><span class="timestamp">2015/11/26 </span>
<span class="twitter"><a href="http://twitter.com/BythonChogo/status/669541778823901185" class="with-short-url" target="_blank"><img src="http://cdn-ak.b.st-hatena.com/images/icon-twitter.png" width="16" height="16" alt="Twitterでのツイートを閲覧" title="Twitterでのツイートを閲覧" /></a><span class="retweet-count require-retweet-count no-retweet-tree" style="display: none"></span></span>    <noscript>
  <a href="/bython-chogo/add.delete?url=http%3A%2F%2Fqiita.com%2FBython-Chogo%2Fitems%2F28475b95e48f76dbc00a&amp;eid=272036974"><img src="http://cdn-ak.b.st-hatena.com/images/delete.gif" alt="ブックマークを削除する" title="ブックマークを削除する" class="inplace-delete-icon" /></a><a
  href="/bython-chogo/add.confirm?url=http%3A%2F%2Fqiita.com%2FBython-Chogo%2Fitems%2F28475b95e48f76dbc00a"><img src="http://cdn-ak.b.st-hatena.com/images/edit.gif" alt="コメントを編集する" title="コメントを編集する" class="inplace-edit-icon" /></a>
</noscript>

</li>

Ok, I'd have to get tags and url. Let's use find_all function.

    soup = BeautifulSoup( html, "lxml" )
    soup.originalEnodings
    hatebu_data = []
    for tag in soup.find_all( 'li', { 'class' : 'entrylist-unit'}): # (1) 
        elements = []
        text = "".join([str.encode('utf8') for str in tag.contents])
        soup2 = BeautifulSoup( text, "lxml")
        elements.append( soup2.a['href'] ) # (2)URL
        elements.append( [unicode(str.string) for str in soup2.find_all( 'a', { 'class': 'user-tag'})] ) #(3) Tags
        elements.append( soup2.find( 'span', { 'class': 'timestamp'}).string)
        hatebu_data.append(elements)
    return hatebu_data

(1) Use find_all to get one book mark HTML source.
(2) in the tag scraped, get url with <a href> tag.
(3) in the tag scraped, get tags with <a class='user-tag'>

then Hatebu_data has list['http://qiita.com/Bython-Chogo/items/2e2e508b91928e5cd9d5',[セルクマ]]. BeautifulSoup is super cool.

Next will be Machine Learning phase with scraped data (finally...). See you again.

<日本語>

こんにちは、日曜日の夕方ですね。なんかだるいっす。また明日から仕事ですねぇ。。。

今日はまたまたスクレイピングのお話です。次は学習データを取得しましょう。これはいつもお世話になっているはてなブックマークでいぜんより取得していたデータを利用します。きょうはそのデータからURLとタグのデータを抜き出します。このデータを利用してタグとURLの文章を学習させるようにします。

なので本日の内容はまたまたBeautifulSoupの使い方になります。ハテブのみの対応したスクリプトになりますが、BeautifulSoupのお勉強にはちょうどよいですね。

ちなみにURLのコンテンツを抜き出していったりするのは著作権的な配慮は必要です。またはてなにも無断でやっていることで、わけのわからないアクセスがたくさん流れているわけで、彼らにアク禁されてもなにも文句はいわれません。そこまで過激でなくてもフォーマットのチェンジにより昨日まで使えたスクリプトが使えなくなってしまうことだってもちろんあるわけです。感謝と謙虚さは忘れてはいけません。

感謝をしたところで、今回抜き出す元データを見てみましょう。いかにハテブの1ブクマ分のHTMLソースを見てみます。これは梅村のアカウントでセルクマ(セルフ・ブックマーク)しているものになります。はてぶさんは普通にアクセスするとJavaScriptを利用していて、今回抜き出したいデータはソースを見ただけではわかりません。が、JavaScriptをオフにしたページもあるので今回そちらから抜き出しています。以下、長いですが今回の読み取るHTMLのタグになります。

<li class="entrylist-unit"
data-eid="272036974"
data-bookmark-count="1"
>
<h3 class="entry entry-title" id="bookmark-272036974" style="background-image:url(http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Fqiita.com%2F)">
<a href="http://qiita.com/Bython-Chogo/items/28475b95e48f76dbc00a" target="_blank" class="entry-link" data-track-click-target="direct">MachineLearning - [機械学習で推奨タグ付け #2] スクレイピングスクリプトの拡張 - Qiita</a> <img src="/images/camera.gif" alt="このエントリーには写真が掲載されています" title="このエントリーには写真が掲載されています" />
<a class="domain" href="/bython-chogo/?url=http%3A%2F%2Fqiita.com%2F" rel="nofollow">qiita.com</a>
</h3>
<ul>

<li class="category"><a href="/hotentry/it" class="category group2">テクノロジー</a></li>

<li class="users"><a href="/entry/qiita.com/Bython-Chogo/items/28475b95e48f76dbc00a" data-track-click-target="entry" title="はてなブックマーク - MachineLearning - [機械学習で推奨タグ付け #2] スクレイピングスクリプトの拡張 - Qiita (1ブックマーク)"><span>1</span> user</a></li>

<img src="http://cdn-ak.b.st-hatena.com/images/keyword.gif?7c8c9ecc9d409bd521163fab85c5da611beba276" alt="キーワード" title="このページに含まれるキーワード" />
<ul class="keywords">

<li class="keyword"><a href="http://d.hatena.ne.jp/keyword/scraper">scraper</a></li>

<li class="keyword"><a href="http://d.hatena.ne.jp/keyword/tag">tag</a></li>

<li class="keyword"><a href="http://d.hatena.ne.jp/keyword/Qiita">Qiita</a></li>

<li class="keyword"><a href="http://d.hatena.ne.jp/keyword/SCRIPT">SCRIPT</a></li>

<li class="keyword"><a href="http://d.hatena.ne.jp/keyword/blog">blog</a></li>

<li class="keyword"><a href="http://d.hatena.ne.jp/keyword/Hatena%20Blog">Hatena Blog</a></li>

<li class="keyword"><a href="http://d.hatena.ne.jp/keyword/encode">encode</a></li>

</ul>

</ul>

<div class="curvebox-header"><div></div></div>
<div class="curvebox-body comment">
<ul class="comment ">

<li data-user="bython-chogo" onmouseover="Hatena.Bookmark.CommentEditor.Hover.create(this, 'http://qiita.com/Bython-Chogo/items/28475b95e48f76dbc00a');" class="mine">    <a href="/bython-chogo/"><img src="http://cdn1.www.st-hatena.com/users/by/bython-chogo/profile_s.gif" class="profile-image" alt="bython-chogo" title="bython-chogo" width="16" height="16" /></a>
<a class="username" href="/bython-chogo/20151126#bookmark-272036974">bython-chogo</a>    <img style='display:none' id="delete-272036974" src="http://cdn-ak.b.st-hatena.com/images/delete.gif" alt="ブックマークを削除する" title="ブックマークを削除する" class="inplace-delete-icon" />
<img src="http://cdn-ak.b.st-hatena.com/images/edit.gif" alt="コメントを編集する" title="コメントを編集する" style="display:none" class="inplace-edit-icon" />
<span class="tags"><a rel="tag" class="user-tag" href="/bython-chogo/%E3%82%BB%E3%83%AB%E3%82%AF%E3%83%9E/">セルクマ</a></span>
<span class="comment"></span><span class="timestamp">2015/11/26 </span>
<span class="twitter"><a href="http://twitter.com/BythonChogo/status/669541778823901185" class="with-short-url" target="_blank"><img src="http://cdn-ak.b.st-hatena.com/images/icon-twitter.png" width="16" height="16" alt="Twitterでのツイートを閲覧" title="Twitterでのツイートを閲覧" /></a><span class="retweet-count require-retweet-count no-retweet-tree" style="display: none"></span></span>    <noscript>
  <a href="/bython-chogo/add.delete?url=http%3A%2F%2Fqiita.com%2FBython-Chogo%2Fitems%2F28475b95e48f76dbc00a&amp;eid=272036974"><img src="http://cdn-ak.b.st-hatena.com/images/delete.gif" alt="ブックマークを削除する" title="ブックマークを削除する" class="inplace-delete-icon" /></a><a
  href="/bython-chogo/add.confirm?url=http%3A%2F%2Fqiita.com%2FBython-Chogo%2Fitems%2F28475b95e48f76dbc00a"><img src="http://cdn-ak.b.st-hatena.com/images/edit.gif" alt="コメントを編集する" title="コメントを編集する" class="inplace-edit-icon" /></a>
</noscript>

</li>

では、この中からURLとタグを抜き出すスクリプトです。

    soup = BeautifulSoup( html, "lxml" )
    soup.originalEnodings
    hatebu_data = []
    for tag in soup.find_all( 'li', { 'class' : 'entrylist-unit'}): # (1) 
        elements = []
        text = "".join([str.encode('utf8') for str in tag.contents])
        soup2 = BeautifulSoup( text, "lxml")
        elements.append( soup2.a['href'] ) # (2)URL
        elements.append( [unicode(str.string) for str in soup2.find_all( 'a', { 'class': 'user-tag'})] ) #(3) Tags
        elements.append( soup2.find( 'span', { 'class': 'timestamp'}).string)
        hatebu_data.append(elements)
    return hatebu_data

(1) find_all関数で先の<li>タグに囲まれたHTMLファイルを抜き取ります。
(2) 1で抜いたHTMLタグ内で<a href>からURLをとる
(3) 1で抜いたHTMLタグ内で<a class='user-tag'>からTag情報をとる

このスクリプトで以下のリストが得られます。

list['http://qiita.com/Bython-Chogo/items/2e2e508b91928e5cd9d5',[セルクマ]]. BeautifulSoup is super cool. 

今日はここまで!次回からはとうとう機械学習のところにはいってきます。今回まで抜き取ったデータをいれこみます。それでは!