65 return datetime_parse(s) |
65 return datetime_parse(s) |
66 else: |
66 else: |
67 return datetime_parse(s) |
67 return datetime_parse(s) |
68 |
68 |
69 |
69 |
70 class WhoisEntry(object): |
70 class WhoisEntry(dict): |
71 """Base class for parsing a Whois entries. |
71 """Base class for parsing a Whois entries. |
72 """ |
72 """ |
73 # regular expressions to extract domain data from whois profile |
73 # regular expressions to extract domain data from whois profile |
74 # child classes will override this |
74 # child classes will override this |
75 _regex = { |
75 _regex = { |
101 else: |
101 else: |
102 self.domain = domain |
102 self.domain = domain |
103 self.text = text |
103 self.text = text |
104 if regex is not None: |
104 if regex is not None: |
105 self._regex = regex |
105 self._regex = regex |
106 |
106 self.parse() |
107 def __getattr__(self, attr): |
107 |
|
108 def parse(self): |
108 """The first time an attribute is called it will be calculated here. |
109 """The first time an attribute is called it will be calculated here. |
109 The attribute is then set to be accessed directly by subsequent calls. |
110 The attribute is then set to be accessed directly by subsequent calls. |
110 """ |
111 """ |
111 try: |
112 for attr, regex in self._regex.items(): |
112 whois_regex = self._regex[attr] |
113 if regex: |
113 except KeyError: |
|
114 raise AttributeError('Unknown attribute: %s' % attr) |
|
115 else: |
|
116 if whois_regex: |
|
117 values = [] |
114 values = [] |
118 for value in re.findall(whois_regex, self.text, re.IGNORECASE): |
115 for value in re.findall(regex, self.text, re.IGNORECASE): |
119 if isinstance(value, basestring): |
116 if isinstance(value, basestring): |
120 # try casting to date format |
117 # try casting to date format |
121 value = cast_date(value.strip(), |
118 value = cast_date(value.strip(), |
122 dayfirst=self.dayfirst, |
119 dayfirst=self.dayfirst, |
123 yearfirst=self.yearfirst) |
120 yearfirst=self.yearfirst) |
127 if len(values) == 1: |
124 if len(values) == 1: |
128 values = values[0] |
125 values = values[0] |
129 elif not values: |
126 elif not values: |
130 values = None |
127 values = None |
131 |
128 |
132 setattr(self, attr, values) |
129 self[attr] = values |
133 return getattr(self, attr) |
130 |
134 |
131 |
135 def __str__(self): |
132 def __setitem__(self, name, value): |
136 """Print all whois properties of domain |
133 super(WhoisEntry, self).__setitem__(name, value) |
137 """ |
134 setattr(self, name, value) |
138 return '\n'.join('%s: %s' % (attr, str(getattr(self, attr))) |
135 |
139 for attr in self.attrs()) |
|
140 |
|
141 def __getstate__(self): |
|
142 """To support pickling |
|
143 """ |
|
144 return self.__dict__ |
|
145 |
|
146 def __setstate__(self, state): |
|
147 self.__dict__ = state |
|
148 |
|
149 def attrs(self): |
|
150 """Return list of attributes that can be extracted for this domain |
|
151 """ |
|
152 return sorted(self._regex.keys()) |
|
153 |
136 |
154 @staticmethod |
137 @staticmethod |
155 def load(domain, text): |
138 def load(domain, text): |
156 """Given whois output in ``text``, return an instance of ``WhoisEntry`` |
139 """Given whois output in ``text``, return an instance of ``WhoisEntry`` |
157 that represents its parsed contents. |
140 that represents its parsed contents. |