When it’s ready.

出来るまで出来ない

BeautifulSoup を諦め HTMLParser使ってみた。

結局、シンプルなHTMLParserを使って作ってみた。id:aodag先生に大変お世話になりました。とりあえづ、昨晩やったこと。HTMLParserで、やってみた。

標準のhandle_dataを変更して、scriptタグとstyleタグとコメントを無視するようにしたTagStripクラスを作る。

# condig:utf-8
from HTMLParser import HTMLParser

class TagStrip(HTMLParser):
   def __init__(self):
       HTMLParser.__init__(self)
       self.datum = []
       self.instyle = False
       
   def handle_data(self, data):
       if data.strip() and not self.instyle:
           self.datum.append(data)
   def getString(self):
       return "".join(self.datum)

   def handle_starttag(self, tag, attrs):
       if tag == 'style' or tag == 'script':
           self.instyle = True

   def handle_endtag(self, tag):
       if tag == 'style' or tag == 'script':
           self.instyle = False

if __name__ == '__main__':
  html = '''
  <html><head>
  <script>
   this is script
  </script>
  </head>
  <body>
  <p>P string</p>
  <div>Div string</div>
  <br>
  <table><tr>
  <td>TD string</td>
  </tr></table>
  </body>
  </html>
  '''
  p = TagStrip()
  p.feed(html)
  print p.getString()

このままhtml食わせたら、問題ないかと思ったら、

<'scr' + 'ipt'>

とかで、パースでこける。あと、文字コードをcontent-typeから決定しようと思ったけど、content-typeの設定されていないページが平気であったりする。これらのを回避する為に、htmlをゲットするときにcharsetを自動判定して、適当に整理するメソッドを作った。

def getHtml(url):
  response = urlopen(url).read()
  response = response.replace("</scr' + 'ipt>", "</script>")
  response = response.replace("<scr' + 'ipt", "<script")
  enc = chardet.detect(response)
  if enc['encoding'].lower() == 'shift_jis':
    return response.decode('shift-jis')
  elif enc['encoding'].lower() == 'euc-jp':
    return unicode(response, 'euc-jp', 'ignore')
  elif enc['encoding'].lower() == 'iso-2022-jp':
    return response.decode('iso-2022-jp')
  else:
    return response

あとは、ひたすらはてブから、linkを引っ張ってきてグルグル回す

# coding:utf-8
from urllib import urlopen
from BeautifulSoup import BeautifulSoup
from splitter import split
from pit import Pit
from pyhatebu import PyHatebu
from htmlStrip import TagStrip
import re
import chardet

# encoding
matchCharset = re.compile(r'charset=(?P<charset>[\w-]+)')

uid = Pit.get('hatena.ne.jp')
h = PyHatebu(uid['login'], uid['password'])


if __name__ == '__main__':
  for i in h.feed():
    print '-' * 80
    print i.title
    print i.link
    str = getHtml(i.link)
    a = TagStrip()
    a.feed(str)
    res = a.getString()
    res = getContent(i.link)
    print res['enc']

今朝見てみたら、id:y_yanbeさんが素敵なコードをくれたので後で試してみる。