BeautifulSoupが処理できないサンプル - 集合知プログラミング::検索とランキング
集合知プログラミング4章の検索とランキングでは、wikipediaのファイルをhttp://www.kiwitobes.com/wikiからダウンロード(クロール)することから始まっています。
さらに、そのファイルを構文解析(parse)して、リンク情報だけを抜き取るようなことをやっていきます。
構文解析はBeautifulSoupというモジュールを使って行います。
しかし、いざやってみるとエラーが出てしまいます。
HTMLParseError: malformed start tag, at line 98, column 20
要は、「変なタグがある」っていうエラー文です。実際、元ファイルのソースの98行20列を見てみると
Retrieved from "<a </div>
という意味不明な文字があったわけです。結局は、これをソースから除去すれば問題解決となります。
置換で対処
もともとのプログラムはこんな感じです。
def crawl(self, pages, depth=2): for i in range(depth): newpages = set(); for page in pages: try: c = urllib2.urlopen(page); except: print "Could not open %s" % page; continue; soup = BeautifulSoup(c.read()); # ここがエラーの源 self.addtoindex(page, soup); links = soup('a'); for link in links: if ('href' in dict(link.attrs)): url = urljoin(page, link['href']); if url[0:4]=='http' and not self.isindexed(url): newpages.add(url); linkText=self.gettextonly(link); self.addlinkref(page, url, linkText); self.dbcommit(); pages = newpages;
ですから、エラー部分に、reモジュールによる置換処理を施します。
def crawl(self, pages, depth=2): for i in range(depth): newpages = set(); for page in pages: try: c = urllib2.urlopen(page); except: print "Could not open %s" % page; continue; # 変更点 # try: soup = BeautifulSoup(re.sub("Retrieved from \"<a","", c.read())); except: print "Could not process %s in BeautifulSoup" % page; continue; # ここまで # self.addtoindex(page, soup); links = soup('a'); for link in links: if ('href' in dict(link.attrs)): url = urljoin(page, link['href']); if url[0:4]=='http' and not self.isindexed(url): newpages.add(url); linkText=self.gettextonly(link); self.addlinkref(page, url, linkText); self.dbcommit(); pages = newpages;
エラーが出ていた一文を丸ごと置換するという荒業で、対処しています。
できれば、不正なタグを除去するような処理をもっと汎用的な書き方でやりたかったんですが、知識不足です(><)
ただ、ここが解決できて、いざクロールを始めてみると、「Not Found」で取得できないページがたくさんありましたw