def _create_table(self, reviews: Tuple[ReviewInfo, ...]) -> str: """レビュー情報一覧から table 要素を作成する Args: reviews (Tuple[ReviewInfo, ...]): レビュー情報一覧 Returns: table タグで囲まれたテキスト """ thead = tag('thead', tag('tr', tag('th', *ReviewInfo._fields))) tr_content_list = list() for review_info in reviews: # レビュー文の処理 review = review_info.review.replace('\n', '<br>') review_info = review_info._replace(review=review) if self.normalize_mode: review = normalize(review) # 列要素を作成 td_content_list = [tag('td', info) for info in review_info] # 行要素を作成 tr = organize_contents(td_content_list, 'tr') tr_content_list.append(tr) tbody = organize_contents(tr_content_list, 'tbody') table_content_list = [thead, tbody] table = organize_contents( table_content_list, 'table', class_='tablesorter tablesorter-{}'.format(TABLE_DESIGN), id=OLD_AND_NEW[1] ) return table
def convert(self, map_jsonfile: Union[str, pathlib.Path]) -> str: """商品レビュー内の文を属性と星評価別に対応付けされた JSON ファイルを見やすいように html ファイルに変換 Args: map_jsonfile (Union[str, pathlib.Path]): 対応付けの結果を格納した JSON ファイル Returns: html で記述されたテキスト """ mapped_data = MappingResult.load(map_jsonfile) self.category = mapped_data.category # head コンテンツ product_name = mapped_data.product title = tag('title', product_name) head_content_list = [*self._head_contents, title] head = organize_contents(head_content_list, 'head') # body コンテンツ body = self._make_body_content(mapped_data) # html コンテンツ html_content_list = [head, body] html = organize_contents(html_content_list, 'html') html = DOC_TYPE + '\n' + html return html
def _convert_review_data_to_body_content( self, reviewdata: ReviewPageJSON) -> str: """レビューデータを html の body 要素に変換する Args: reviewdata (ReviewPageJSON): Amazon レビューデータ Returns: body タグで囲まれたテキスト """ real_reviews = reviewdata.real_reviews num_reviews_text = 'レビュー数:{}'.format(real_reviews) total_reviews = reviewdata.total_reviews if total_reviews != real_reviews: num_reviews_text = '{} / {}'.format(num_reviews_text, total_reviews) reviews = reviewdata.reviews h3_content_list = _make_stars_texts(reviews, reviewdata.stars_distribution) # <body>コンテンツの用意 body_content_list = [ tag('h1', reviewdata.product), tag('h2', tag('a', '商品レビューページ', href=reviewdata.link)), tag('h2', 'メーカー:{}'.format(reviewdata.maker)), tag('h2', '評価:{}'.format(reviewdata.average_stars)), tag('h2', num_reviews_text), *h3_content_list, ] # <table>コンテンツの用意 table = self._create_table(reviews) # <body>コンテンツの再設定 body_content_list.append(table) body = organize_contents(body_content_list, 'body') return body
def _create_heatmap_table( self, heatmap_dict: HeatmapDict, anchor_dict: AnchorDict ) -> str: """属性と星評価別にレビュー文中の文数をヒートマップにして可視化したものを table タグで作成 Args: heatmap_dict (HeatmapDict): 属性と星評価別にレビュー文中の文数をまとめた辞書 anchor_dict (AnchorDict): 属性と星評価別にレビュー文の情報をまとめたリストとアンカーを格納した辞書 Returns: ヒートマップを実装した table タグ """ tr_content_list = [tag('th', '属性', class_='first')] star_strs = tuple(STAR_DISPLAY_DICT[star_str] for star_str in STAR_CORRESPONDENCE_DICT.values()) tr_content_list.extend([tag('th', star_str) for star_str in star_strs[:-1]]) tr_content_list.append(tag('th', star_strs[-1], class_='last')) tr = organize_contents(tr_content_list, 'tr') thead = tag('thead', tr) jump_fmt = '#{}' tbody_content_list = [] for attr in heatmap_dict: if attr != "その他": attr_anchor = tag('a', attr, href=jump_fmt.format(self._attr_ja2en[attr])) td_header = tag('td', attr_anchor, class_='stats-title') td_content_list = [td_header] num_texts_and_anchor_props = zip(heatmap_dict[attr].values(), anchor_dict[attr].values()) for num_texts, anchor_prop in num_texts_and_anchor_props: anchor = tag('a', num_texts, href=jump_fmt.format(anchor_prop.link_id)) td_content = tag('td', anchor) td_content_list.append(td_content) tr = organize_contents(td_content_list, 'tr', class_='stats-row') tbody_content_list.append(tr) tbody = organize_contents(tbody_content_list, 'tbody') table = organize_contents( [thead, tbody], 'table', class_='heat-map', cellpadding='0', cellspacing='0', border='0', id='heat-map-3') return table
def _itemize_text_by_attr_and_star( self, attr_to_star_map: Attr2StarMap, anchor_dict: AnchorDict ) -> Tuple[str, ...]: """属性と星評価別にレビュー文中の文を列挙する Args: attr_to_star_map (Attr2StarMap): 属性と星評価別にレビュー文中の文を格納した辞書 anchor_dict (AnchorDict): 属性と星評価別にレビュー文の情報をまとめたリストとアンカーを格納した辞書 Returns: 列挙された文一覧 """ display_fmt = '{}:{}' enum_content_list = list() for en_attr in attr_to_star_map: attr = self._mapper.en2ja[en_attr] enum_content_list.append(tag('h2', attr, id=en_attr)) for star_str, anchor_prop in anchor_dict[attr].items(): link_id, review_text_info_list = anchor_prop star_disp = STAR_DISPLAY_DICT[star_str] enum_content_list.append( tag('h3', display_fmt.format(attr, star_disp), id=link_id)) if review_text_info_list: li_content_list = list() for review_text_info in review_text_info_list: text = review_text_info.text summary = tag('summary', text) review = normalize(review_text_info.review) marked_text = tag('span', text, class_='sentence-marker') marked_review = review.replace(text, marked_text) details_content_list = [ summary, marked_review.replace('\n', '<br>') ] details = organize_contents(details_content_list, 'details') li_content_list.append(tag('li', details)) ul = organize_contents(li_content_list, 'ul') enum_content_list.append(ul) return tuple(enum_content_list)
def convert(self, reviewjson: Union[str, pathlib.Path]) -> str: """jsonファイルを読み込み、htmlフォーマットに変換 Args: reviewjson (Union[str, pathlib.Path]): jsonファイルのパス Returns: JSON ファイルの中身を html に変換したもの(BeautifulSoup による整形済み) """ reviewdata = ReviewPageJSON.load(reviewjson) head = self._make_head_content(reviewdata.product) body = self._convert_review_data_to_body_content(reviewdata) html = organize_contents((head, body), 'html') html = DOC_TYPE + '\n' + html # BeautifulSoupで整形 bs = BeautifulSoup(html, 'lxml') return bs.prettify()
def _make_body_content(self, mapped_data: MappingResult) -> str: """html の body タグを作成 Args: mapped_data (MappingResult): 対応付けされた結果 Returns: body タグ """ body_content_list = [] # h1コンテンツ h1_content = tag('h1', mapped_data.product) body_content_list.append(h1_content) # h2コンテンツ review_info_content = [ tag('h2', 'レビュー情報'), tag('h3', tag('a', '商品レビューページ(Amazon)', href=mapped_data.link)), tag('h3', 'メーカー:{}'.format(mapped_data.maker)), tag('h3', '評価:{}'.format(mapped_data.average_stars)), tag('h3', 'レビュー数:{}'.format(mapped_data.total_review)), tag('h3', '総文数:{}'.format(mapped_data.total_text)), ] body_content_list.extend(review_info_content) # heatmapコンテンツ heatmap_content_list = [tag('h2', '属性別での文分布')] attr_to_star_map = mapped_data.mapping heatmap_dict, anchor_dict = self._reorganize_mapped_data(attr_to_star_map) heatmap_table = self._create_heatmap_table(heatmap_dict, anchor_dict) heatmap_content_list.append(heatmap_table) body_content_list.extend(heatmap_content_list) # 属性別のレビュー列挙 enum_content_list = self._itemize_text_by_attr_and_star(attr_to_star_map, anchor_dict) body_content_list.extend(enum_content_list) # bodyコンテンツ body = organize_contents(body_content_list, 'body') return body
def _make_head_content(self, product_name: str) -> str: """head コンテンツの作成""" title = tag('title', product_name) head_content_list = [*self.head_contents, title] head = organize_contents(head_content_list, 'head') return head