]> git.phdru.name Git - bookmarks_db.git/blob - Robots/parse_html.py
Updated to m_lib version 1.2. Extended support for Mozilla.
[bookmarks_db.git] / Robots / parse_html.py
1 #! /usr/local/bin/python -O
2 """
3    HTML Parser
4
5    Written by BroytMann, Jun 2002 - May 2003. Copyright (C) 1997-2003 PhiloSoft Design
6 """
7
8
9 import sys
10 current_charset = sys.getdefaultencoding()
11 DEFAULT_CHARSET = "windows-1251" # Stupid default for Russian Cyrillic
12
13
14 from HTMLParser import HTMLParseError
15 from m_lib.net.www.html import HTMLParser as _HTMLParser
16
17
18 class HTMLHeadDone(Exception): pass
19
20
21 class HTMLParser(_HTMLParser):
22    def __init__(self, charset=None):
23       _HTMLParser.__init__(self)
24       self.charset = charset
25       self.meta_charset = 0
26       self.title = ''
27       self.refresh = ''
28
29    def end_head(self):
30       raise HTMLHeadDone()
31
32
33    def do_meta(self, attrs):
34       http_equiv = ""
35       content = ""
36
37       for attrname, value in attrs:
38          if value:
39             value = value.strip()
40             if attrname == 'http-equiv':
41                http_equiv = value.lower()
42             elif attrname == 'content':
43                content = value
44
45       if (not self.charset) and (http_equiv == "content-type"):
46          try:
47             # extract charset from "text/html; foo; charset=UTF-8; bar;"
48             self.charset = content.lower().split('charset=')[1].split(';')[0]
49             self.meta_charset = 1 # Remember that the charset was retrieved from
50                                   # META tag, not from the Content-Type header
51          except IndexError:
52             pass
53
54       if http_equiv == "refresh":
55          self.refresh = content
56
57
58    def start_title(self, attrs):
59       self.accumulator = ''
60
61    def end_title(self):
62       if not self.title: # use only the first title
63          self.title = self.accumulator
64
65
66 import re
67 entity_re = re.compile("(&#[0-9]+;)")
68
69 def recode_entities(title, charset):
70    output = []
71    for part in entity_re.split(title):
72       if entity_re.match(part):
73          part = unichr(int(part[2:-1])).encode(charset, "replace")
74       output.append(part)
75
76    return ''.join(output)
77
78
79 def parse_html(filename, charset=None, log=None):
80    infile = open(filename, 'r')
81    parser = HTMLParser(charset)
82
83    for line in infile:
84       try:
85          parser.feed(line)
86       except (HTMLParseError, HTMLHeadDone):
87          break
88
89    infile.close()
90
91    try:
92       parser.close()
93    except (HTMLParseError, HTMLHeadDone):
94       pass
95
96    title = parser.title
97
98    if not parser.charset:
99       ascii = 1
100       for c in title:
101          if not (32 <= ord(c) <= 127): # non-ASCII character
102             ascii = 0
103             break
104       if not ascii:
105          parser.charset = DEFAULT_CHARSET
106
107    if parser.charset and (parser.charset <> current_charset):
108       try:
109          if parser.meta_charset:
110             if log: log("   META charset   : %s" % parser.charset)
111          else:
112             if log: log("   charset        : %s" % parser.charset)
113          if log: log("   title          : %s" % title)
114          title = unicode(title, parser.charset, "replace").encode(current_charset, "replace")
115          if log: log("   current charset: %s" % current_charset)
116          if log: log("   converted title: %s" % title)
117       except LookupError:
118          if log: log("   unknown charset: `%s' or `%s'" % (parser.charset, current_charset))
119
120    parser.title = recode_entities(title, current_charset)
121    return parser
122
123
124 if __name__ == '__main__':
125    import sys
126    parser = parse_html(sys.argv[1])
127    print parser.charset
128    print parser.title
129    print parser.refresh