0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

javaで大量のHTMLから正規表現置換をして、要素を取り出す

Last updated at Posted at 2019-09-02

今回やりたいこと

HTMLのテキストデータを読み込みjavaで読み込み それをlistに入れた後
listに入っているStringのデータを読み込んで それを正規表現で置換、処理をしてallに保存すること

想定

大量の同じようなファイルに一括で処理をかけること
javaでのファイル読み込みからの一行ずつのListに追加は完了していること

利点 

同じ正規表現で引っかかるデータを別のものとして保存できる
複数ヒットに対応
ヒットしなかったときの例外処理を行うことでデータの数がずれない

仕様

listの中のString のデータを全探索して
目当てのデータが見つかった場合 それを置換してall(String) に格納する仕様。
目当てのデータをいくつ目からから格納するか
目当てのデータがなかった時は どうするのかなどは 引数によって決定できる
""の時は全くの無操作
他の時はその指定されている文字を追加してカンマ区切りにする。

引数 意味
be 正規表現置換前のString
af 正規表現置換後のString
no 検索に引っかからなかった時の文字列
s いくつ目のヒットから考えるか
num いくつまでのヒットを考えるか
be_set ここに入れた文字列がヒットしてから検索を開始する
af_set ここに入れた文字列がヒットしたら検索を終える

ソースコードのフロー

  • listの要素の全てに対して

    • beのヒット確認
    • afのヒット確認
    • be_flagがtrueの時
      • 置換前とのヒット確認し、置換しsave(list)に追加
        • ただし ヒット確認要素数が1の時はここでallに追加してreturn
      • afのヒット確認(ヒットしたらbreak)
  • saveの全ての要素に対して

    • save.size = 0 の例外処理
    • save.size と 検索のヒット数の引数との大小関係の例外処理
    • 要素数全てをallに追加

呼び出し方

call
sp("<.+><.+-(.+)\"></i></div>"
,"$1q"
,"noq"
,1
,14
,"<.+>データ1のテーブル</h3>"
,"<.+>データ2のテーブル</h3>");

このような場合 HTMLでの記述
データ1のテーブル
から
データ2のテーブル
までの要素で
<.+><.+-(.+)\"></i></div>
の正規表現にヒットするものを
$1q
で置き換えます($1は正規表現置換におけるヒット後の置き換え記号かっこの中でヒットしたものをそののまま要素として扱う。
データがなかった時は
noq
で置き替わります.これは後から処理するときに空行だとデータのセルの場所がずれてしまうための処理です

その後 カンマが追加されて終了です。
利点として、データ1とデータ2の書式が同じだった場合でもきちんと正しいデータを取ることができます。

ソースコード

grobal

ArrayList<String> list = new ArrayList<String>();
String all = "";
String qq = "qqqqqqqqq";  //ヒットしないであろう文字列
public static void add_all(String index){
    all = all + index + kn;
// kn は データを追加する際のデータの区切り文字 debug時は"\n" release時は","を推奨
}
over
//引数を少なくした場合のオーバーロード
//qqはまあヒットしないと思われる文字列
//引数3つの時は常に一つの要素を探す
public static void sp(String be,String af,String no){
    int s = 1; int num =1;
    sp(be,af,no,s,num,qq,qq);
  }
  public static void sp(String be,String af,String no,int s,int num){
    sp(be,af,no,s,num,qq,qq);
  }
sp
public static void sp(String be,String af,String no,int s,int num ,String be_set,String af_set){
  int i;
  boolean be_flag = false;
  boolean af_flag = false;
  boolean cutset = false;
  //開始終了フラグ入力されてない時は 全検索をする
  if(be_set.equals(qq) && af_set.equals(qq)){
    be_flag=true;
  }
  //検索ヒット数を一個にしていた時は cutsetのフラグで高速処理可能
  if(s ==1 && num ==1){
    cutset = true;
  }
  ArrayList<String> save = new ArrayList<String>();
  save.clear();//いらないけど一応
  //リストサイズ分の繰り返し 
  for(i = 0;i < list.size();i++){
    //リストデータ入手
    String line = list.get(i);
    //開始フラグ操作
    if(line.matches(be_set)){
      be_flag=true;
    }
    //終了フラグ操作
    if(line.matches(af_set) && be_flag){
      break;
    }
    if(line.matches(be) && be_flag){
      line = line.replaceAll(be,af);
      save.add(line);
      deb(0,line);
      //データを一個しか検索しない時の処理 高速化を狙う
      if(cutset){
        String tem = save.get(0);
        add_all(tem+",");
        return;
      }
    }
  }

  //全部データを読んだ後
  //ヒットがなかった時
  //置換後データが""でなければ引数のnoを追加する
  if(save.size() == 0){
    if(!no.equals(""))add_all(no);
  //そうでない時
  }else{
    //例外処理 入力数とヒット数を揃える
    if(save.size() < num){
      num = save.size();
    }
    if(save.size() < s){
      s = save.size();
    }
    //引数での指定分だけallに追加
    for(i=0;i<num;i++){
      String tem = save.get(s+i-1);
      add_all(tem);
    }
  }
  //データ反映後はカンマ区切り
  if(!no.equals(""))add_all(",");
}

あとがき

これは構造をしっかり考えずに必要なものを足していった結果こうなりましたが、私にとってはですが、悪くないと思います。
私はこれを HTMLからデータを読み込むのに使いました。pythonのライブラリを使ってもいいと思いますがその発想に至ったのが結構後だったためこのような形式をとりました。

0
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?