HiNativeのスクレイピング

HiNative とは気軽にネイティブ・スピーカーに質問ができるQ&Aサービスなのですが、今回はHiNativeについて深くは触れません。下の写真のようなスレッドから必要な情報(ユーザー名、書き込み時刻、書き込み内容)だけを取り出すスクリプトを作成します。なお、質問者が最も役に立ったと思う回答には featured_answer という称号が与えられます。これは外国語学習者が、どのような回答を求めているかという観点で非常に重要な情報です。しかし、会話が重複してしまうため、今回は割愛することとしました。

 

 

タグ解析には主としてpythonを使用しました。python初心者が先ず悩んでしまう事は、pythonには2.X系と3.X系が有ることです。両者は言語体系としても、かなり違いが大きいのですが、2.X系は既にサポート終了しています。にもかかわらず、普通に python と打鍵すると2.X系が起動してしまいます。

とまぁ、前途多難なのですがXpathが思ったように使えなかったため python の勉強から始めました。なお、これには

【Python】BeautifulSoupでclassを指定して要素を取得する方法【スクレイピング】 - narupoのブログ や python3でwebスクレイピング(Beautiful Soup) - Qiita

 が、大変役にたちました。

 

#!/bin/bash
target_url=`getparstr $# "$*" "URL"`
if [ -z ${target_url} ]
then
 exit
fi temp=`mktemp ./XXX` python3 << _PYTHON_ > ${temp} from bs4 import BeautifulSoup from urllib.request import urlopen # 一般的なHTMLの取得 # パーサーにより解析されオブジェクト soup が作成される target_url = '${target_url}' html = urlopen(target_url) data = html.read() html = data.decode('utf-8') soup = BeautifulSoup(html, "html.parser") # 「最も役に立った回答」を削除します # ただし「最も役に立った回答」が存在しないスレッドもあるため、 # その場合は何もしません try: soup.find('div',class_='container_fukidashi featured_answer_fukidashi').extract() except AttributeError as e: pass # 配列 bubbles に各吹き出しの情報を取得します bubbles = soup.find_all('div',class_='container_fukidashi') # 各吹き出しから必要なタグを取得します i=0 while i<len(bubbles)-1: # 最後の吹き出しは広告のため使わない bubble = bubbles[i] # ユーザー名 user = bubble.find('a',class_='username') print(user.text) # 書き込み時刻 time = bubble.find('span',class_='timeago') time = time.attrs['title'] print(time) # 会話 # 最初の会話だけは question を鍵にタグを探します # それ以外は answer を鍵とします if i==0: conversation=bubble.find('div',class_='mod_question_content_decorated') else: conversation=bubble.find('div',class_='answer_links') conversation=conversation.find('a',class_='in_place_edit') print(conversation) print() i=i+1 _PYTHON_ # 最後にHTMLの改行記号である <br/> タグを\nに置き換え # 不要なタグを削除します cat ${temp} |\ sed -e "s/<br\/>/\n/g" |\ prog/tag_remover.sh

tag_remover.sh については sedを用いたtag_remover - あるStray Engineer の日記 を参考にして下さい。

所望の情報を取り出すことができました。書き込み時刻については Zuluタイムで表示されているようですね。