単一ドメインを走査する(URLに日本語を含む場合)
- 作者: Ryan Mitchell,嶋田健志,黒川利明
- 出版社/メーカー: オライリージャパン
- 発売日: 2016/03/18
- メディア: 大型本
- この商品を含むブログ (2件) を見る
更新が久しぶりになっちゃいました。
「PythonによるWebスクレイピング」を読んでいて気になったところがあったのでまとめました。
気になったところは、
3.1 単一ドメインを走査する の
from urllib.request import urlopen from bs4 import BeautifulSoup import datetime import random import re random.seed(datetime.datetime.now()) def getLinks(articleUrl): html = urlopen("http://en.wikipedia.org"+articleUrl) bsObj = BeautifulSoup(html, "html.parser") return bsObj.find("div", {"id":"bodyContent"}).findAll("a", href=re.compile("^(/wiki/)((?!:).)*$")) links = getLinks("/wiki/Kevin_Bacon") while len(links) > 0: newArticle = links[random.randint(0, len(links)-1)].attrs["href"] print(newArticle) links = getLinks(newArticle)
です。
これ自体は正常に動きます。ですが、これを日本語版Wikipediaで使おうとするとエラーが起きてしまいました。
理由を考えてみたら……
・日本語版WikipediaのURLは「https://ja.wikipedia.org/wiki/日本語名」となっている
→サンプルコードの
html = urlopen(“http://en.wikipedia.org”+articleUrl)
bsObj = BeautifulSoup(html, “html.parser”)
でエラーが起きてしまう。
なので、urlopenの引数の日本語をURLエスケープさせる必要がある。
個人的にとった対処方法は
url = “https://ja.wikipedia.org/wiki/”+quote_plus(articleUrl,encoding=‘utf-8’)
html = urlopen(url)
bsObj = BeautifulSoup(html,‘html.parser’)
です。
quote関数に関しては、下記を参照。
21.8. urllib.parse — URL を解析して構成要素にする — Python 3.5.2 ドキュメント
ただ、こうやって解決すると、サンプルコードのwhile以下も変更しなきゃいけません。
newArticle = links[random.randint(0, len(links)-1)].attrs[“href”]
newArticle = unquote(newArticle)
newArticle = newArticle.replace(“/wiki/”,‘’)
print(newArticle+“\n”)
links = getLink(newArticle)
getLink関数の引数は、エスケープ前のstr型が欲しいので、unquote関数で元に戻す。
/wiki/を取り除いているのは、日本語部分のみをURLエスケープさせてたいからです。
もっとスマートなやり方があるような気がしますが、それは宿題に。
from urllib.request import urlopen from urllib.parse import urlparse, quote_plus, unquote from bs4 import BeautifulSoup import re import random import datetime random.seed(datetime.datetime.now()) def getLink(articleUrl): url = "https://ja.wikipedia.org/wiki/"+quote_plus(articleUrl,encoding='utf-8') print(url) html = urlopen(url) bsObj = BeautifulSoup(html,'html.parser') return bsObj.find("div",{"id":"bodyContent"}).findAll("a",href=re.compile("^(/wiki/)((?!:).)*$")) links = getLink("松本憲生") while len(links) > 0: newArticle = links[random.randint(0, len(links)-1)].attrs["href"] newArticle = unquote(newArticle) newArticle = newArticle.replace("/wiki/",'') print(newArticle+"\n") links = getLink(newArticle)
以下、実行結果。
https://ja.wikipedia.org/wiki/%E6%9D%BE%E6%9C%AC%E6%86%B2%E7%94%9F 十五少年漂流記 https://ja.wikipedia.org/wiki/%E5%8D%81%E4%BA%94%E5%B0%91%E5%B9%B4%E6%BC%82%E6%B5%81%E8%A8%98 プリキュアカラフルコレクション https://ja.wikipedia.org/wiki/%E3%83%97%E3%83%AA%E3%82%AD%E3%83%A5%E3%82%A2%E3%82%AB%E3%83%A9%E3%83%95%E3%83%AB%E3%82%B3%E3%83%AC%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3 キャラクターソング https://ja.wikipedia.org/wiki/%E3%82%AD%E3%83%A3%E3%83%A9%E3%82%AF%E3%82%BF%E3%83%BC%E3%82%BD%E3%83%B3%E3%82%B0 八奈見乗児 https://ja.wikipedia.org/wiki/%E5%85%AB%E5%A5%88%E8%A6%8B%E4%B9%97%E5%85%90 とっても!ラッキーマン https://ja.wikipedia.org/wiki/%E3%81%A8%E3%81%A3%E3%81%A6%E3%82%82%21%E3%83%A9%E3%83%83%E3%82%AD%E3%83%BC%E3%83%9E%E3%83%B3 テレビせとうち https://ja.wikipedia.org/wiki/%E3%83%86%E3%83%AC%E3%83%93%E3%81%9B%E3%81%A8%E3%81%86%E3%81%A1 山陽中継局