0

今朝、マーヴェリックのガソリンスタンドのすべてのガソリン価格を配列に解析する小さなプロジェクトに取り組みたいと思いました。私のコードで「汚れている」と感じる唯一の部分は、変数へのhtmlの実際の解析です。必要なデータを取得するために indexOf と部分文字列を使用していますが、それを行うためのよりクリーンな方法が必要だと感じていますか? とにかく、これが私のコードです。コンパイルしてうまく動作しますが、私が望むほどきれいではありません。

maverik.javaには、メイン メソッドとプロジェクトのコードの大部分が含まれています。 maverikObj.javaには、ゲッターとセッター、コンストラクター、および toString メソッドが含まれています。

コンソール データを取得しているガソリン スタンドを変更するには、maverik.java の 90 行にある配列 println の数値を変更するだけです。将来のリビジョンには、ユーザーの要求に基づいて表示されるデータを制御するメソッドが含まれる予定です。

価格を含む HTML の例を次に示します。

html4 = "<b>Maverik Store 4</b><br/>5200 Chinden Blvd<br>Boise, ID<br>208-376-0532<br><center><b></b></center><br /><font color=red>Fuel Prices -- Updated every 30 minutes</font><br /><div><div style=\"float: left; width: 70%; text-align:right;\">Adventure Club Card</div><div style=\"float: right; width: 30%; text-align:center;\">Retail</div><br /><div style=\"float: left;width: 30%;\">Unleaded:</div><div style=\"float: left; width: 30%; text-align:center;\"> 3.379</div><div style=\"float: right; width: 30%; text-align:center;\"> 3.399</div><br /><div style=\"float: left;width: 30%;\">Blend 89:</div><div style=\"float: left; width: 30%; text-align:center;\"> 3.469</div><div style=\"float: right; width: 30%; text-align:center;\"> 3.499</div><br /><div style=\"float: left;width: 30%;\">Blend 90:</div><div style=\"float: left; width: 30%; text-align:center;\"> 3.549</div><div style=\"float: right; width: 30%; text-align:center;\"> 3.579</div><br /><div style=\"float: left;width: 30%;\">Premium:</div><div style=\"float: left; width: 30%; text-align:center;\"> 3.599</div><div style=\"float: right; width: 30%; text-align:center;\"> 3.639</div><br /><div style=\"float: left;width: 30%;\">Diesel:</div><div style=\"float: left; width: 30%; text-align:center;\"> 4.039</div><div style=\"float: right; width: 30%; text-align:center;\"> 4.059</div>";

現在、住所、都市、州、電話番号、および各ステーションで可能な 8 種類のガスすべてを解析しています。(無鉛、ブレンド 87、88、89、99、プレミアム、ディーゼル)。ただし、いくつかの html エントリにはリストされている 8 つすべてが含まれておらず、ほとんどのエントリには 8 つの可能な燃料タイプのうち 4 つまたは 5 つしか含まれていないため、少し複雑になります。したがって、このデータを解析するために、2 つの方法を使用しました。

住所、都市、州、電話番号は、次を使用して解析されます。

if(line.contains(" = \"<b>Maverik Store")&&!line.contains("Coming Soon!")){ address=splitLine[3].substring(0,splitLine[3].length()-3).replace(" ", " "); city=splitLine[4].substring(0,splitLine[4].length()-7); state=splitLine[4].substring(splitLine[4].length()-5,splitLine[4].length()-3); phone=splitLine[5].substring(0,splitLine[5].length()-3);

燃料タイプは if else ステートメントを使用して解析されます。if ステートメントを使用してデータが存在する場合はデータを記録し、else ステートメントを使用して 0.0 double を記録します。これは、コンストラクターがすべての燃料タイプに何らかの値を持つ必要があるためです。

if(line.indexOf("Unleaded:")>0){
    unleaded=Double.parseDouble(line.substring(line.indexOf("Unleaded:")+147, line.indexOf("Unleaded:")+152));
}
else{
    unleaded=0.0;
}

ご覧のとおり、必要なデータを取得するために多くの部分文字列と indexOf 文字列メソッドを使用しています。私の懸念は、これが私が望むデータを取得するための非常に静的な方法であることです。コードをクリーンアップする方法についてのヒントをいただければ幸いです。=)

4

3 に答える 3

4

オーケー、最初は、より美しい (私の意見によると) まったく異なるコーディング スタイルを使用します。しかし、いくつかの異なるコーディング スタイルを探して、最も気に入ったものを決定することをお勧めします。

私は XML ファイルで同様の問題を抱えていましたが、かなり混乱していました。最善の方法は、独自の XMLParser を作成することです。HTML は XML 構造と変わらないため、HTML ファイルの解析にも使用できます。

非常に大変な作業なので、私の実装を提供できます (必要に応じて教えてください。もちろん、それは OpenSource です)。開発者が望むものを素早く手に入れるように設計されています。使用例:

XMLDocument document = new XMLDocument("yourXMLSourceCode");
XMLNode node = document.getNode("html.body.div");
String attribute = document.get("html.body.div?id");
String content = document.get("html.body.div.input");
XMLNode[] mynodes = document.getNode("html.body").getSubNodes("input");

このように「SAX パーサー」または「XML パーサー」を検索すると、他の解決策が見つかる場合があります。

私はあなたがそれを使うことができると思います.そのコードでいくつかの小さなトリックを行うと、HTMLに完全に使用できます.

それ以外の場合は、HTML の作業中に行ったように、HTMLParser を使用できます。私はJsoupで非常に良い経験をしています。

于 2013-03-17T07:18:04.747 に答える
1

あまり細かく言うことはありませんが、正規表現を使用してhtml(またはxml)を解析することは、今日の世界のすべての悪の原因です。(わかりました、小さな誇張ですが、ほんの少しです。)

私たちの現代のhtmlである本質的に厄介な混乱を処理するために最善を尽くそうとするユーティリティがたくさんあります。Java用の1つは「jsoup」です。例えば:

package foo;
import org.jsoup.*;
import org.jsoup.nodes.*;
import org.jsoup.select.*;

public class Bar {
  public static void main(String[] args) {
    //Document doc = Jsoup.connect(url).get();
    String html = "<html>...</html>";
    Document doc = Jsoup.parse(html);
    Elements divs = doc.select("div");
    for (Element e : divs) {
       System.out.println(e.text());
    }
  }
}

次に、サンプルのhtmlスニペットを指定しても(読者の演習として多くが残されています):

$ java -cp jsoup-1.7.2.jar:.  foo.Bar

Adventure Club Card Retail Unleaded: 3.379 3.399 Blend 89: 3.469 3.499 Blend 90: 3.549 3.579 Premium: 3.599 3.639 Diesel: 4.039 4.059
Adventure Club Card
Retail
Unleaded:
3.379
3.399
Blend 89:
3.469
3.499
Blend 90:
3.549
3.579
Premium:
3.599
3.639
Diesel:
4.039
4.059
于 2013-03-17T09:41:58.527 に答える
-1

次のような正規表現を使用できます。

BufferedReader reader = new BufferedReader (
    new InputStreamReader (
        new URL ("https://www.maverik.com/locations/").
            openStream ()));

Pattern linePattern = Pattern.compile ("<b>Maverik Store ([^<]*)</b><br/>([^<]*)<br>([^<]*)<br>([^<]*)<br><center><b></b></center><br /><font color=red>Fuel Prices -- Updated every 30 minutes</font>");
Pattern pricePattern = Pattern.compile ("<div style=\\\\\"float: left;width: 30%;\\\\\">([^<]*)</div><div style=\\\\\"float: left; width: 30%; text-align:center;\\\\\">([^<]*)</div><div style=\\\\\"float: right; width: 30%; text-align:center;\\\\\">([^<]*)</div><br />");

String line;
while ((line = reader.readLine ()) != null)
{
    Matcher lineMatcher = linePattern.matcher (line);
    if (lineMatcher.find ())
    {
        System.out.println ("Store #: " + lineMatcher.group (1));
        System.out.println ("Store Address 1: " + lineMatcher.group (2));
        System.out.println ("Store Address 2: " + lineMatcher.group (3));
        System.out.println ("Store Phone: " + lineMatcher.group (4));

        Matcher priceMatcher = pricePattern.matcher (line);
        while (priceMatcher.find ())
        {
            System.out.println (priceMatcher.group (1) + priceMatcher.group (2) + priceMatcher.group (3));
        }
        System.out.println ();
    }
}

私にとっては、次のように出力されます。

Store #: 4
Store Address 1: 5200 Chinden Blvd
Store Address 2: Boise, ID
Store Phone: 208-376-0532
Unleaded: 3.379 3.399
Blend 89: 3.469 3.499
Blend 90: 3.549 3.579
Premium: 3.599 3.639

Store #: 6
Store Address 1: 8561 West State
Store Address 2: Boise, ID
Store Phone: 208-853-1226
Unleaded: 3.379 3.399
Blend 88: 3.849 3.879
Blend 89: 3.469 3.499
Blend 90: 3.549 3.579

Store #: 7
Store Address 1: Highway   310  North
Store Address 2: Bridger, MT
Store Phone: 406-662-3356
Unleaded: 3.249 3.269
Blend 87: 3.499 3.529
Blend 89: 3.499 3.529
Premium: 3.489 3.529

Store #: 130
Store Address 1: 105  South  200  West
Store Address 2: Bountiful, UT
Store Phone: 801-292-6792
Unleaded: 3.269 3.289
Blend 87: 3.359 3.389
Blend 89: 3.439 3.469

Store #: 134
Store Address 1: 105  East Winnemucca
Store Address 2: Winnemucca, NV
Store Phone: 775-623-5948
Unleaded: 3.559 3.579
Blend 87: 3.649 3.679
Blend 89: 3.729 3.759

Store #: 135
Store Address 1: 1571  North  Main
Store Address 2: Sheridan, WY
Store Phone: 307-672-7010
Unleaded: 3.159 3.179

Store #: 136
Store Address 1: 222  South  Main
Store Address 2: Lyman, WY
Store Phone: 307-786-2705
Unleaded: 3.269 3.289
Blend 87: 3.359 3.389
Blend 89: 3.439 3.469
Premium: 3.489 3.529

Store #: 137
Store Address 1: 7th  & Main
Store Address 2: Snowflake, AZ
Store Phone: 928-536-7511
Unleaded: 3.539 3.559
Blend 89: 3.629 3.659
Blend 90: 3.709 3.739

...
于 2013-03-17T07:26:51.240 に答える