質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.59%

HTMLからのテキスト抽出に関する問題

受付中

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 552

gran-1123

score 18

 前提・実現したいこと

現在HTMLデータから特定の条件にマッチしたテキストのみを正規表現を用いて抽出し、年表形式で出力するプログラムを作成しています。

しかし自分が設定した正規表現の抽出パターン以外にも有用な抽出テキストを見落としている可能性を加味して新たな抽出パターンを模索していた際に私は、「年号を抽出する正規表現パターンの「absobe_pattern_history」が抽出された際に存在する前後の文も抽出すれば年表に有用な情報を抽出できるのではないかと考えつきました。

ですが、それを実現させるソースコードの書き方が分からないため、そのような挙動を実現させる手法の回答をお願いしたいです。

ソースコード 

#coding:utf-8
import re
from bs4 import BeautifulSoup
import pandas as pd

results_hi = []#年号を格納しておく関数
results_t = []#作品タイトルを格納しておく関数
results_ha = []#出来事を格納しておく関数

absobe_pattern_history = '^U.C.[0-9]{4}'#宇宙世紀の年号

absobe_pattern_title = '^機動戦士ガンダム'#作品タイトル抽出パターン1
absobe_pattern_title2 = '^機動戦士[\t\n\r\f\v一-龥ぁ-んァ-ンa-zA-ZΖ0-9_ー・.]{1,}ガンダム'#作品タイトル抽出パターン2
absobe_pattern_title3 = '^機動戦士ガンダム[ \t\n\r\f\v一-龥ぁ-んァ-ンa-zA-ZΖ0-9_ー・.]{1,}'#作品タイトル抽出パターン3
absobe_pattern_title4 = '^機動戦士[\t\n\r\f\v一-龥ぁ-んァ-ンa-zA-ZΖ0-9_ー・.]{1,}ガンダム[ \t\n\r\f\v一-龥ァ-ンa-xA-ZΖ0-9_ー・]{1,}'#作品タイトル抽出パターン4

absobe_pattern_happen = '[\t\n\r\f\v一-龥ァ-ンa-zA-Z0-9_ー・]{1,}戦争'#出来事抽出パターン1
absobe_pattern_happen2 = '[\t\n\r\f\v一-龥ァ-ンa-zA-Z0-9_ー・]{1,}戦役'#出来事抽出パターン2
absobe_pattern_happen3 = '[\t\n\r\f\v一-龥ァ-ンa-zA-Z0-9_ー・]{1,}紛争'#出来事抽出パターン3
absobe_pattern_happen4 = '[\t\n\r\f\v一-龥ァ-ンa-zA-Z0-9_ー・]{1,}抗争'#出来事抽出パターン4
absobe_pattern_happen5 = '[\t\n\r\f\v一-龥ァ-ンa-zA-Z0-9_ー・]{1,}事件'#出来事抽出パターン5

# encoding は取得したページの文字コードを選択
filepath = '/home/urai/crawling/gandamu/gandamu uchuuseiki/1.html'
with open(filepath , encoding='utf-8') as f:
    html = f.readlines()
    for i in html:
        soup = BeautifulSoup(i, 'html.parser')#SoupでHTMLからデータを取る
        for text in soup.find_all(text=True):#Tabを取り除く
                if text.strip():#テキストであるか判定
                    results_hi.append(re.findall(absobe_pattern_history, text))#条件に適合した文(年号)を抽出、results_hiに格納

                    results_t.append(re.findall(absobe_pattern_title, text))#同上(作品名)、results_tに格納
                    results_t.append(re.findall(absobe_pattern_title2, text))
                    results_t.append(re.findall(absobe_pattern_title3, text))
                    results_t.append(re.findall(absobe_pattern_title4, text))

                    results_ha.append(re.findall(absobe_pattern_happen, text))#同上(出来事)、results_haに格納
                    results_ha.append(re.findall(absobe_pattern_happen2, text))
                    results_ha.append(re.findall(absobe_pattern_happen3, text))
                    results_ha.append(re.findall(absobe_pattern_happen4, text))
                    results_ha.append(re.findall(absobe_pattern_happen5, text))
    f.close()

    UC_history = [hi[0] for hi in results_hi if  hi != []]#抽出データから空のリストを取り除いた上で、入れ子構造を解消

    UC_title = [t[0] for t in results_t if  t != []]#抽出データから空のリストを取り除いた上で、入れ子構造を解消

    UC_happen = [ha[0] for ha in results_ha if  ha != []]#抽出データから空のリストを取り除いた上で、入れ子構造を解消

    his_list = sorted(set(UC_history), key=UC_history.index)#重複を排除
    tit_list = sorted(set(UC_title), key=UC_title.index)#上に同じ
    hap_list = sorted(set(UC_happen), key=UC_happen.index)#上に同じ

    his_list.sort()#年代順に並び替える

# 最長のリストにあわせNone要素を詰め込む
his_l,tit_l,hap_l = [],[],[]
from itertools import zip_longest
for his,tit,hap in zip_longest(his_list,tit_list,hap_list):
    his_l.append(his)#年号のリストの中身を格納
    tit_l.append(tit)#作品名のリストの中身を格納
    hap_l.append(hap)#出来事のリストの中身を格納

df = pd.DataFrame({'年代':his_l,'出来事':hap_l,'作品名':tit_l},columns=['年代','出来事','作品名'])
df.to_html('ret.html',index=False)

 補足情報(FW/ツールのバージョンなど)

'/home/urai/crawling/gandamu/gandamu uchuuseiki/1.html'はWikipediaの「宇宙世紀」ページのHTMLデータになります。
元のソースコードは可能な限り消さないようにお願いします。
また、抽出をお願いしたデータはどの関数に格納したのかの明言もお願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • dice142

    2018/12/04 17:09

    ここはコーディング依頼をする場ではないです。

    キャンセル

  • 退会済みユーザー

    2018/12/05 09:03

    複数のユーザーから「問題・課題が含まれていない質問」という意見がありました
    teratailでは、漠然とした興味から票を募るような質問や、意見の主張をすることを目的とした投稿は推奨していません。
    「編集」ボタンから編集を行い、質問の意図や解決したい課題を明確に記述していただくと回答が得られやすくなります。

  • 退会済みユーザー

    2018/12/06 10:51

    複数のユーザーから「やってほしいことだけを記載した丸投げの質問」という意見がありました
    「質問を編集する」ボタンから編集を行い、調査したこと・試したことを記入していただくと、回答が得られやすくなります。

回答 1

0

teratailでは丸投げの質問は回答されません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る