1515import traceback
1616import zipfile
1717
18- from lxml import etree
18+ from lxml import html
1919from markupsafe import Markup
2020
2121from hyperreal .index import Index
2727class HansardCorpus (SqliteBackedCorpus ):
2828 CORPUS_TYPE = "Australian Federal Hansard"
2929
30- table_fields = ["date" , "house" , "debate_title" , "subdebate_title" , "speech" ]
31-
3230 def __init__ (self , db_path ):
3331 """
3432 A corpus to wrap around the data model found in https://github.com/SamHames/hansard-tidy
@@ -49,21 +47,18 @@ def docs(self, doc_keys=None):
4947 self .db .execute (
5048 """
5149 select
52- speech.speech_id,
53- speech.date,
54- speech.house,
55- speech_number,
56- debate.debate_id,
57- debate.debate,
58- debate.subdebate_1,
59- debate.subdebate_2,
60- xml_url,
61- html_url,
62- speech_xml
63- from speech
50+ page_id,
51+ url,
52+ access_time,
53+ debate_id,
54+ pp.date,
55+ pp.house,
56+ pp.parl_no,
57+ title,
58+ page_html
59+ from proceedings_page pp
6460 inner join debate using(debate_id)
65- inner join transcript using(transcript_id)
66- where speech.speech_id = ?
61+ where page_id = ?
6762 """ ,
6863 [key ],
6964 )
@@ -75,90 +70,60 @@ def docs(self, doc_keys=None):
7570 self .db .execute ("release docs" )
7671
7772 def index (self , doc ):
78- root = etree .fromstring (doc ["speech_xml" ])
79-
80- # TODO: This will need additional work to work with all the different
81- # hansard schemas.
82- talkers = root .xpath ("//talker" )
83- for elem in talkers :
84- elem .clear ()
73+ root = html .fromstring (doc ["page_html" ])
8574
86- speech_tokens = tokens (" " .join (root .itertext ()))
75+ page_tokens = tokens (" " .join (root .itertext ()))
8776
88- speech_date = date .fromisoformat (doc ["date" ])
89- speech_month = speech_date .replace (day = 1 )
90- speech_year = speech_month .replace (month = 1 )
77+ page_date = date .fromisoformat (doc ["date" ])
78+ month = page_date .replace (day = 1 )
79+ year = month .replace (month = 1 )
9180
9281 return {
93- "speech " : speech_tokens ,
82+ "page " : page_tokens ,
9483 "house" : set ([doc ["house" ]]),
95- "debate" : set ([doc ["debate" ]]),
96- "subdebate_1" : set ([doc ["subdebate_1" ]]),
97- "subdebate_2" : set ([doc ["subdebate_2" ]]),
9884 "debate_id" : set ([doc ["debate_id" ]]),
99- "speech_date" : set ([speech_date .isoformat ()]),
100- "speech_month" : set ([speech_month .isoformat ()]),
101- "speech_year" : set ([speech_year .isoformat ()]),
102- }
103-
104- def pretty_index (self , doc ):
105- root = etree .fromstring (doc ["speech_xml" ])
106-
107- # TODO: This will need additional work to work with all the different
108- # hansard schemas.
109- talkers = root .xpath ("//talker" )
110- for elem in talkers :
111- elem .clear ()
112-
113- speech_tokens = presentable_tokens (" " .join (root .itertext ()))
114-
115- speech_date = date .fromisoformat (doc ["date" ])
116-
117- return {
118- "speech" : speech_tokens ,
119- "house" : set ([doc ["house" ]]),
120- "debate" : set ([doc ["debate" ]]),
121- "subdebate_1" : set ([doc ["subdebate_1" ]]),
122- "subdebate_2" : set ([doc ["subdebate_2" ]]),
123- "speech_date" : set ([speech_date .isoformat ()]),
124- "transcript_url" : set ([doc ["html_url" ]]),
85+ "date" : set ([page_date .isoformat ()]),
86+ "month" : set ([month .isoformat ()]),
87+ "year" : set ([year .isoformat ()]),
88+ "parl_no" : set ([doc ["parl_no" ]]),
89+ # Index the formatting elements so we can systematically investigate them
90+ "html_classes" : {
91+ str (clss ) for elem in root .iter () for clss in elem .classes
92+ },
93+ "html_tags" : {str (elem .tag ) for elem in root .iter ()},
12594 }
12695
12796 def render_docs_html (self , doc_keys ):
12897 """Return the given documents as HTML."""
12998 docs = []
13099
131100 for key , doc in self .docs (doc_keys = doc_keys ):
132- tree = etree .fromstring (doc ["speech_xml" ])
133-
134- text = " " .join (s for s in tree .itertext ())
135- text = "<br />" .join (s for s in text .splitlines () if s .strip ())
136-
137101 summary = ", " .join (
138- doc [item ]
139- for item in ("date" , "house" , "debate" , "subdebate_1" , "subdebate_2" )
140- if doc [item ]
102+ doc [item ] for item in ("date" , "house" , "title" ) if doc [item ]
141103 )
142104
143105 doc_html = """
144106 <details>
145107 <summary>{}</summary>
146108 <div>
147- <a href="{}">See full day </a>
109+ <a href="{}">See in context </a>
148110 </div>
149111 <div>{}</div>
150112 </details>
151113 """ .format (
152- summary , doc ["html_url " ], text
114+ summary , doc ["url " ], doc [ "page_html" ]
153115 )
154116
155117 docs .append ((key , Markup (doc_html )))
156118
157119 return docs
158120
159121 def keys (self ):
160- """The speeches are the central document."""
161- return (r ["speech_id" ] for r in self .db .execute ("select speech_id from speech" ))
122+ """The pages are the central document."""
123+ return (
124+ r ["page_id" ]
125+ for r in self .db .execute ("select page_id from proceedings_page" )
126+ )
162127
163128
164129if __name__ == "__main__" :
@@ -167,28 +132,33 @@ def keys(self):
167132 except FileNotFoundError :
168133 pass
169134
135+ db = "tidy_hansard.db"
136+ db_index = "tidy_hansard_index.db"
137+
170138 logging .basicConfig (filename = "process_hansard.log" , level = logging .INFO )
171- corpus = HansardCorpus ("hansard.db" )
139+ corpus = HansardCorpus (db )
172140
173141 args = sys .argv [1 :]
174142
175143 mp_context = mp .get_context ("spawn" )
176144 with cf .ProcessPoolExecutor (mp_context = mp_context ) as pool :
177- idx = Index ("hansard_index.db" , corpus = corpus , pool = pool )
145+ idx = Index (db_index , corpus = corpus , pool = pool )
178146
179147 if "index" in args :
180- idx .index (doc_batch_size = 100000 , position_window_size = 1 )
148+ idx .index (doc_batch_size = 50000 , index_positions = True )
181149
182150 if "cluster" in args :
183151 idx .initialise_clusters (
184- n_clusters = 512 , min_docs = 10 , include_fields = ["speech" ]
152+ n_clusters = 256 , min_docs = 100 , include_fields = ["page" ]
153+ )
154+ idx .refine_clusters (
155+ iterations = 50 , group_test_batches = 32 , group_test_top_k = 2
185156 )
186- idx .refine_clusters (iterations = 50 , group_test_batches = 100 )
187157
188158 index_server = hyperreal .server .SingleIndexServer (
189- "hansard_index.db" ,
159+ db_index ,
190160 corpus_class = HansardCorpus ,
191- corpus_args = ["hansard.db" ],
161+ corpus_args = [db ],
192162 pool = pool ,
193163 )
194164 engine = hyperreal .server .launch_web_server (index_server )
0 commit comments