一个采鸟用java查询COVID-19小工具
这是一个简易的爬虫。
我是一个java新手,写出的代码可能有亿些
bug或不对的地方,还请大佬们见谅,指点,帮忙改正,谢谢读者。
本文所使用到的技术
正则表达式
Java基础
数据https://covid19.who.int
导入所使用的类
import java.net.*; //网络类
import java.io.*; //IO流
import java.util.regex.*; //正则表达式
import java.text.*; //格式化
import java.util.*; //工具类
import javax.net.ssl.*; //异常类
成员信息
private URL u;
private long confirmedCases, deathCases;//已确诊与已死亡病例人数
private String range;//统计范围
private boolean exception;//执行中是否发生了异常,以确保数据是否可以安全返回
private Date time;//最后统计时间
得到网站的数据,如果没有发生异常,
则返回网站的信息,得到原数据,进而进行筛选可用数据
private StringBuilder getStreamData() throws IOException {
System.out.println("正在连接服务器");
BufferedReader br = new BufferedReader(new InputStreamReader(u.openStream(), "UTF-8"));
System.out.println("开始接收数据...");
StringBuilder sb = new StringBuilder(10*10000);
for(String t;(t = br.readLine()) != null;)
sb.append(t);
br.close();
return sb;
}
得到了杂乱的数据,接着进行筛选
正则表达式有用处了,我发现中间的这段文字可以进行匹配,如下
private void setValue(CharSequence val) throws ParseException
{
System.out.println("数据处理中");
Pattern regex = Pattern.compile("<span\\sclass=\".*?\">(.*?)<\\/span>");
Matcher main = regex.matcher(val);
Matcher spare = Pattern.compile("<span\\sclass=\".*?\">([\\d,]+)<!--\\s-->").matcher(val);
if(main.find())
range = main.group(1);
if(main.find())
time = new SimpleDateFormat("hh:mmaa dd MMMMM yyyy", Locale.US).parse(main.group(1).replaceAll("CES?T,\\s", ""));
////这里的写法纯属是我乱写的,耦合性太高,大佬们多多见谅
time.setHours(time.getHours() + 6);
if(spare.find())
confirmedCases = Long.parseLong(spare.group(1).replace(",", ""));
if(spare.find())
deathCases = Long.parseLong(spare.group(1).replace(",", ""));
}
匹配完毕,信息设置成功,在这里我知道了细
节的重要性: CES?T,\s这一 条正则中,WHO中
原来是CEST,我原来的正则是CET,\s后来他们
改为CET,导致了我整个程序无法运行(耦合
性太高),懒了好长时间,本以为是改结构
了,没想到就这一个字母(QWQ)
那么一个简单的爬虫搞好了,再重写一下
toString()吧
在public String toString()
{
if(exception)
return "";
// TODO: Implement this method
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm ");
StringBuilder sb = new StringBuilder(128);
DecimalFormat df = new DecimalFormat("####,####,####");
//2:16pm CEST, 18 August 2020
//2:16pm 18 August 2020
sb.append("统计时间:" + sdf.format(time) + "\r\n");
sb.append("区域范围:" + range + "\r\n");
sb.append("确诊病例:" + df.format(confirmedCases) + "\r\n");
sb.append("死亡病例:" + df.format(deathCases) + "\r\n");
sb.append("数据来源:" + u.getHost());
return sb.toString();
}
读者,是不是发现了exception有没有都一-样
哈哈哈哈,我大E了,
确实,用处不大,我觉
得它可以设置为一个Exception类,值为null,
下面是赋值代码(就是捕捉异常而已啦)
private void handle()
{
try
{
u = new URL("https://covid19.who.int");
setValue(getStreamData());
return;
}
catch(SSLProtocolException e)
{
System.out.println("发生错误,正在重连");
handle();
return;
}
catch(UnknownHostException e)
{
System.out.println("请检查网络连接,网址是否过时");
}
catch(ParseException e)
{
System.out.println("格式化时间时发生错误");
}
catch(NullPointerException e)
{
e.printStackTrace();
}
catch(ConnectException ce)
{
System.out.println("服务器无响应");
}
catch(IOException ioe)
{
System.out.println("发生IO错误");
ioe.printStackTrace();
}
catch(Exception e)
{
System.out.println("数据接收失败");
}
exception = true;//如果没有发生异常,则通过return结束本方法,程序已经运行到这个地方,证明有异常发生
}
这样,整个程序就完结了,就这样了。
这是整个程序的代码
import java.net.*; //网络类
import java.io.*; //IO流
import java.util.regex.*; //正则表达式
import java.text.*; //格式化
import java.util.*; //工具类
import javax.net.ssl.*; //异常类
public class Viewer
{
private URL u;
private long confirmedCases, deathCases;
private String range;
private boolean exception;
private Date time;
public Viewer()
{
handle();
}
private void handle()
{
try
{
u = new URL("https://covid19.who.int");
setValue(getStreamData());
return;
}
catch(SSLProtocolException e)
{
System.out.println("发生错误,正在重连");
handle();
return;
}
catch(UnknownHostException e)
{
System.out.println("请检查网络连接,网址是否过时");
}
catch(ParseException e)
{
System.out.println("格式化时间时发生错误");
}
catch(NullPointerException e)
{
e.printStackTrace();
}
catch(ConnectException ce)
{
System.out.println("服务器无响应");
}
catch(IOException ioe)
{
System.out.println("发生IO错误");
ioe.printStackTrace();
}
catch(Exception e)
{
System.out.println("数据接收失败");
}
exception = true;
}
private StringBuilder getStreamData() throws IOException
{
System.out.println("正在连接服务器");
BufferedReader br = new BufferedReader(new InputStreamReader(u.openStream(), "UTF-8"));
System.out.println("开始接收数据...");
StringBuilder sb = new StringBuilder(10*10000);
for(String t;(t = br.readLine()) != null;)
sb.append(t);
br.close();
return sb;
}
private void setValue(CharSequence val) throws ParseException
{
System.out.println("数据处理中");
Pattern regex = Pattern.compile("<span\\sclass=\".*?\">(.*?)<\\/span>");
Matcher main = regex.matcher(val);
Matcher spare = Pattern.compile("<span\\sclass=\".*?\">([\\d,]+)<!--\\s-->").matcher(val);
if(main.find())
range = main.group(1);
if(main.find())
time = new SimpleDateFormat("hh:mmaa dd MMMMM yyyy", Locale.US).parse(main.group(1).replaceAll("CES?T,\\s", ""));
time.setHours(time.getHours() + 6);
if(spare.find())
confirmedCases = Long.parseLong(spare.group(1).replace(",", ""));
if(spare.find())
deathCases = Long.parseLong(spare.group(1).replace(",", ""));
}
@Override
public String toString()
{
if(exception)
return "";
// TODO: Implement this method
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm ");
StringBuilder sb = new StringBuilder(128);
DecimalFormat df = new DecimalFormat("####,####,####");
//2:16pm CEST, 18 August 2020
//2:16pm 18 August 2020
sb.append("统计时间:" + sdf.format(time) + "\r\n");
sb.append("区域范围:" + range + "\r\n");
sb.append("确诊病例:" + df.format(confirmedCases) + "\r\n");
sb.append("死亡病例:" + df.format(deathCases) + "\r\n");
sb.append("数据来源:" + u.getHost());
return sb.toString();
}
public boolean getException()
{
return this.exception;
}
}
因为这个程序耦合性太高,可能无法使用,但
是目前(2021-02-16 08:54)还能正常使用。
正在连接服务器
Not need to boost !
开始接收数据。
数据处理中
统计时间: 2021-02- 15
22 :05
区域范围: Globally
确诊病例: 1,0857 , 9352
死亡病例: 239 ,6408
数据来源: covid19.who. int