- いったんwebapp.RequestHandlerを継承したクラスを作ってバリデーション処理を共通させる
別にバリデーションに限らないが
class AbstractHandler(webapp.RequestHandler): def v_url(self, url): if not url: logging.warning('url is blank.') return url = url.encode('utf-8') if url.startswith(self.request.host_url): logging.warning('url startswith host_url.') return return url class EditHandler(AbstractHandler): def get(self): url = self.v_url(self.request.get('url')) if not url: self.message('パラメータが不正です') return class SetHandler(AbstractHandler): def get(self): url = self.v_url(self.request.get('url')) if not url: self.message('パラメータが不正です') return
関数でやってもいいけど、まとめておくと理解しやすくていい
- 動いてるアプリのソースをそのまま返す
rootPath = os.path.dirname(__file__) appPath = os.path.join(rootPath, 'hoge.py') class ViewSourceHandler(webapp.RequestHandler): def get(self): all = open(appPath, 'r').read() self.response.headers['Content-Type'] = 'text/plain; charset=utf-8' self.response.out.write(all)
そのまんま。
ファイルの書き込みがダメなだけなので、これで問題なくソースを返す。
- テキストとテキストの差を取る(更新された部分だけ抽出)
def getDiff(strOld, strNew): diff = [] for line in ndiff(strOld.splitlines(), strNew.splitlines()): if line.startswith('+'): diff.append(line[1:]) return '\n'.join(diff)
- urlfetchしたHTMLからテキストだけを抽出する
まず文字コードを判定する
charsetの候補を拾っては試していく
urlfetchのレスポンスの
-
- headers['Content-Type']にcharset=〜の指定があればそれを試す(レスポンスヘッダ)
- contentにcharset=〜が含まれていればそれを試す(HTMLファイル内のヘッダ)
def isCharset(charset): #正しいcharsetであるかを調べる try: unicode('hoge', charset) return True except: return False
if res.headers.has_key('Content-Type'): c = re.search(r'charset=([0-9a-zA-Z\-_]+)', res.headers['Content-Type']) if c: charset = c.group(1) if not isCharset(charset): charset = None if not charset: c = re.search(r'charset=([0-9a-zA-Z\-_]+)', unicode(html[:1000], 'shift-jis', errors='replace')) if c: charset = c.group(1) if not isCharset(charset): charset = None
どちらにも指定が無い場合もあるし、x-sjisとか指定されてて、チェックで撥ねられる場合もある(pythonがencodeに失敗する=不正なcharset、としている)
その場合は、
-
- chardetで推測する
それも失敗することがあるので
-
- 最後はshift-jis決め打ち
if not charset: try: charset = chardet.detect(html)['encoding'] except: charset = 'shift-jis' html = unicode(html, charset, errors='replace')
unicodeになったらそれをパースする
パーサはhtml5libを使うのがいい
parser = html5lib.HTMLParser(tree=html5lib.treebuilders.getTreeBuilder("beautifulsoup"))
bs = parser.parse(html)
あとはBeautifulSoupを使ってタイトルとテキストを抜き出す
#http://python.g.hatena.ne.jp/y_yanbe/20081025/1224910392 def getNavigableStrings(soup): if isinstance(soup, NavigableString): if type(soup) not in (Comment, Declaration) and soup.strip(): yield soup elif soup.name not in ('script', 'style', 'title', 'noscript'): for c in soup.contents: for g in getNavigableStrings(c): yield g
title = bs.find('title') if title: title = '\n'.join(title.contents) title = re.sub(r'\n', ' ', title) else: title = '' text = '\n'.join(getNavigableStrings(bs)) text = re.sub(r'<([^>]+)?>', '', text) return ( title, text )
HTMLコードが漏れることがあるのでその部分は消してる
BeautifulSoupについては調べてないので暫定的な対処
- ソース全体は