今天早上,我决定我想做一个小项目,将maverik加油站的所有汽油价格解析为一个数组。我可以轻松地完成大部分工作,我觉得代码中唯一“脏”的部分是将html实际解析为变量。我正在使用indexOf和子字符串来获取所需的数据,我觉得必须有一种更清洁的方式来做到这一点?无论如何,这是我的代码,它可以编译并很好地工作,只是没有我想要的那么干净。

maverik.java包含项目的主要方法和大量代码。
maverikObj.java包含getter和setter,构造函数和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种html条目,所以有点棘手,而大多数html条目只有8种可能的4种或5种。因此,我使用两种方法来解析此数据。

地址,城市,州,电话号码使用以下方式解析:

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倍的数据,因为我的构造函数要求所有燃料类型都具有一定的值。

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


如您所见,我使用许多子字符串和indexOf字符串方法来获取所需的数据。我担心这是获取所需数据的极其静态的方法,因此我觉得这是一种非常肮脏的处理方式。感谢有关如何清理代码的任何提示! =)

最佳答案

您可以使用如下正则表达式:

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

...

10-06 15:36