今天早上我决定开展一个小项目,将maverik加油站的所有汽油价格分解成阵列。我的大部分工作相当容易,我觉得在我的代码中唯一的“脏”部分是将html实际解析为变量。我正在使用indexOf和substrings来获取我想要的数据,我觉得必须有一个更清洁的方法来做到这一点?无论如何这里是我的代码,它编译和工作很好,不像我想的那么干净。
maverik.java包含项目的主要方法和大部分代码。 maverikObj.java包含getter和setter,constructor和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,Premium,Diesel)。它有点棘手,因为一些html条目没有列出所有8个,大多数只有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字符串方法来获取我想要的数据。我担心这是获取我想要的数据的一种非常静态的方法,因此我觉得它是一种非常肮脏的做事方式。任何有关如何清理我的代码的提示都表示赞赏! =)
答案 0 :(得分: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解析器”(例如this)找到其他解决方案。
我认为你可以使用它,使用该代码做一些小技巧,你可以完美地将它用于HTML。
否则,我在使用HTML时所做的就是使用HTMLParser。我对Jsoup有很好的经验。
答案 1 :(得分:1)
不要在它上面写太多,但使用正则表达式来解析html(甚至是xml)是当今世界上所有邪恶的根源。 (好吧,有点夸张,但只是一点点。)
有许多实用工具试图尽力处理我们现代html中固有的杂乱混乱。一个用于Java的是“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
答案 2 :(得分:-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
...