围棋棋谱一般被保存为sgf格式,要想在自己的网站中实现打谱功能,必要要会解析sgf文件,取出里面的对局信息和落子,楼主现在用一种比较简单的方法来解析它

说明:楼主所用的棋谱是从新浪围棋里下载来的,示例用的是第10届中国围棋龙星战半决赛江维杰VS辜梓豪

文件内容如下(其他sgf格式也差不多,就是有些字段的名字换了一下)

(
TE[第10届中国围棋龙星战半决赛]
RD[2019-05-28]
PC[中国]
TM[0]
LT[30]
LC[10]
KO[7.5]
RE[黑中盘胜]
PB[江维杰]
BR[九段]
PW[辜梓豪]
WR[九段]
GK[1]
TC[];B[pd];W[dp];B[qp];W[dd];B[np];W[qc];B[qd];W[pc];B[nc];W[oc];B[od];W[nb];B[fq];W[hq]
;B[cc];W[cd];B[dc];W[ec];B[eb];W[fb];B[fc];W[ed];B[gb];W[db];B[fa];W[cb];B[fo];W[dm]
;B[jq];W[jp];B[kp];W[ip];B[ko];W[kq];B[kr];W[lq];B[ir];W[pp];B[po];W[qo];B[pq];W[hr]
;B[mq];W[in];B[bc];W[bb];B[er];W[dq];B[gn];W[il];B[gl];W[dk];B[cr];W[dr];B[ds];W[bq]
;B[el];W[dl];B[en];W[ij];B[fj];W[di];B[qn];W[fh];B[jk];W[ik];B[im];W[jm];B[hm];W[jo]
;B[jl];W[kn];B[lp];W[kl];B[kk];W[ll];B[lk];W[lo];B[lr];W[mk];B[ki];W[nl];B[hi];W[ni]
;B[mm];W[ml];B[jh];W[mc];B[nd];W[rc];B[pi];W[pk];B[ef];W[fd];B[lm];W[km];B[cg];W[ff]
;B[co];W[cn];B[cp];W[cq];B[do];W[bo];B[bk];W[bl];B[ci];W[gj];B[dh];W[gi];B[dj];W[ei]
;B[ej];W[ck];B[hh];W[gk];B[fg];W[eg];B[gg];W[eh];B[gh];W[fi];B[df];W[dg];B[ch];W[cf]
;B[bf];W[ce];B[fe];W[gf];B[ge];W[hf];B[ee];W[ig];B[hj];W[hk];B[ii];W[hc];B[gd];W[gc]
;B[hd];W[id];B[ic];W[fb];B[ie];W[jd];B[fc];W[hb];B[he];W[je];B[if];W[jf];B[hg];W[ng]
;B[qg];W[qj];B[md];W[lc];B[ob];W[mb];B[rd])

需要的属性说明如下

[TE]:比赛标题

[RD]比赛时间

[PC]比赛地点

[KO]贴目

[RE]比赛结果

[PB]黑方姓名

[BR]黑方水平(职业)

[PW]白方名字

[WR]白方水平

;B[]黑方落子坐标

;W[]白棋落子坐标

实现

    1.先创建一个落子类,属性是落子的颜色、x坐标,与坐标以及步数

public class Point {private String color;private int x;private int y;private int step;public Point() {super();// TODO Auto-generated constructor stub}public Point(String color, int x, int y,int step) {super();this.color = color;this.x = x;this.y = y;this.step = step;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}public int getX() {return x;}public void setX(int x) {this.x = x;}public int getY() {return y;}public void setY(int y) {this.y = y;}public int getStep() {return step;}public void setStep(int step) {this.step = step;}}

2.创建棋谱类,记录所有信息

//棋谱
public class ChessManual {private int manualid;private String title;// 比赛private String time;// 比赛时间private String dict;// 地点private float tiemu;// 贴目private String result;// 结果private String blackName;// 黑方private String blacklevel;// 黑方水平private String whiteName;// 白方private String whitelevel;// 白方水平private List<Point> playList;// 落子顺序public ChessManual() {super();// TODO Auto-generated constructor stub}public ChessManual(String title, String time, String dict, float tiemu, String result, String blackName,String blacklevel, String whiteName, String whitelevel) {super();this.title = title;this.time = time;this.dict = dict;this.tiemu = tiemu;this.result = result;this.blackName = blackName;this.blacklevel = blacklevel;this.whiteName = whiteName;this.whitelevel = whitelevel;}public ChessManual(int manualid, String title, String time, String dict, float tiemu, String result,String blackName, String blacklevel, String whiteName, String whitelevel) {super();this.manualid = manualid;this.title = title;this.time = time;this.dict = dict;this.tiemu = tiemu;this.result = result;this.blackName = blackName;this.blacklevel = blacklevel;this.whiteName = whiteName;this.whitelevel = whitelevel;}public int getManualid() {return manualid;}public void setManualid(int manualid) {this.manualid = manualid;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getTime() {return time;}public void setTime(String time) {this.time = time;}public String getDict() {return dict;}public void setDict(String dict) {this.dict = dict;}public float getTiemu() {return tiemu;}public void setTiemu(float tiemu) {this.tiemu = tiemu;}public String getResult() {return result;}public void setResult(String result) {this.result = result;}public String getBlackName() {return blackName;}public void setBlackName(String blackName) {this.blackName = blackName;}public String getBlacklevel() {return blacklevel;}public void setBlacklevel(String blacklevel) {this.blacklevel = blacklevel;}public String getWhiteName() {return whiteName;}public void setWhiteName(String whiteName) {this.whiteName = whiteName;}public String getWhitelevel() {return whitelevel;}public void setWhitelevel(String whitelevel) {this.whitelevel = whitelevel;}public List<Point> getPlayList() {return playList;}public void setPlayList(List<Point> playList) {this.playList = playList;}}

3.解析类

1.取内容函数:取到指定路径文件里的所有内容

//拿到文件内容public String getContent(String path) throws IOException {String result="";FileReader reader = new FileReader(path);BufferedReader br = new BufferedReader(reader);String line;while ((line = br.readLine()) != null) {result+=line;}return result;}

如果是网络文件,就通过url拿到

//拿到文件内容public String getContent(String path) throws IOException {URL url =new URL(path); // 创建URLURLConnection urlconn = url.openConnection(); // 试图连接并取得返回状态码urlconn.connect();HttpURLConnection httpconn =(HttpURLConnection)urlconn;String result="";InputStreamReader reader = new InputStreamReader(urlconn.getInputStream(),"GBK");BufferedReader br = new BufferedReader(reader); // 建立一个对象,它把文件内容转成计算机能读懂的语言String line;//网友推荐更加简洁的写法while ((line = br.readLine()) != null) {result+=line;}return result;}

2.我们发现文件的有效信息都在 ’[‘ 和 ’]‘ 里,而且 '['前面都带有表明内容含义的字段,因此我们需要做的是取一个字符串中指定         开头字符和指定结尾字符中间的子字符串集合,因此我用了正则表达式来取

public static List<String> getStrContainData(String str, String start, String end){List<String> result = new ArrayList<>();String regex = start + "(.*?)" + end;Pattern pattern = Pattern.compile(regex);Matcher matcher = pattern.matcher(str);while(matcher.find()){String key = matcher.group(1);if(!key.contains(start) && !key.contains(end)){result.add(key);}}return result;}

3.有了这个方法,那取信息就很方便了

比如取标题是这样

ChessManual chessManual = new ChessManual();
//取比赛标题
List<String> result1 = getStrContainData(content, "TE\\[", "\\]");
for(String key : result1) {chessManual.setTitle(key);
}

后面都差不多,最后讲讲取下棋步骤,列表中的每一项都是两个英文字母,而棋盘排列是从a开始的,因此只要求出两个字母在26个英文字母的位置即可得到坐标

楼主这里先取所有黑棋下的,在取白棋下棋,由于每个点都带有下棋步数,因此只需要这个list按下棋步数排列即可

//落子String s = "abcdefghijklmnopqrstuvwxyz";List<Point> moves = new ArrayList<Point>();//取出所有的黑棋落子List<String> result10 = getStrContainData(content,";B\\[","\\]");int i=0;for(String str : result10) {int x = s.indexOf(str.charAt(0));int y = s.indexOf(str.charAt(1));Point point = new Point("black",x,y,i*2+1);moves.add(point);i++;}//取出所有的白棋落子int j=0;List<String> result11 = getStrContainData(content,";W\\[","\\]");for(String str : result11) {int x = s.indexOf(str.charAt(0));int y = s.indexOf(str.charAt(1));Point point = new Point("white",x,y,j*2+2);moves.add(point);j++;}moves.sort(new Comparator<Point>() {@Overridepublic int compare(Point o1, Point o2) {if(o1.getStep()>o2.getStep()) {return 1;}else {return -1;}}});

下面是解析的全部代码

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;import com.yizaiqianqiu.entity.ChessManual;
import com.yizaiqianqiu.entity.Point;import net.sf.json.JSONObject;public class ParseSGF {public ChessManual parseSGF(String path) throws IOException {ChessManual chessManual = new ChessManual();String content = getContent(path);String s = "abcdefghijklmnopqrstuvwxyz";//取比赛标题List<String> result1 = getStrContainData(content, "TE\\[", "\\]");for(String key : result1) {chessManual.setTitle(key);}//取比赛时间List<String> result2 = getStrContainData(content, "RD\\[", "\\]");for(String key : result2) {chessManual.setTime(key);}//取比赛地点List<String> result3 = getStrContainData(content, "PC\\[", "\\]");for(String key : result3) {chessManual.setDict(key);}//取出贴目List<String> result4 = getStrContainData(content, "KO\\[", "\\]");for(String key : result4) {chessManual.setTiemu(Float.parseFloat(key));}//取出结果List<String> result5 = getStrContainData(content, "RE\\[", "\\]");for(String key : result5) {chessManual.setResult(key);}//取出黑棋姓名List<String> result6 = getStrContainData(content,"PB\\[","\\]");for(String key : result6) {chessManual.setBlackName(key);}//取出黑棋水平List<String> result7 = getStrContainData(content,"BR\\[","\\]");for(String key : result7) {chessManual.setBlacklevel(key);}//取出白棋姓名List<String> result8 = getStrContainData(content,"PW\\[","\\]");for(String key : result8) {chessManual.setWhiteName(key);}//取出白棋水平List<String> result9 = getStrContainData(content,"WR\\[","\\]");for(String key : result9) {chessManual.setWhitelevel(key);}//落子List<Point> moves = new ArrayList<Point>();//取出所有的黑棋落子List<String> result10 = getStrContainData(content,";B\\[","\\]");int i=0;for(String str : result10) {int x = s.indexOf(str.charAt(0));int y = s.indexOf(str.charAt(1));Point point = new Point("black",x,y,i*2+1);moves.add(point);i++;}//取出所有的白棋落子int j=0;List<String> result11 = getStrContainData(content,";W\\[","\\]");for(String str : result11) {int x = s.indexOf(str.charAt(0));int y = s.indexOf(str.charAt(1));Point point = new Point("white",x,y,j*2+2);moves.add(point);j++;}moves.sort(new Comparator<Point>() {@Overridepublic int compare(Point o1, Point o2) {if(o1.getStep()>o2.getStep()) {return 1;}else {return -1;}}});chessManual.setPlayList(moves);String str =JSONObject.fromObject(chessManual).toString();System.out.println(str);return chessManual;}//拿到文件内容public String getContent(String path) throws IOException {String result="";FileReader reader = new FileReader(path);BufferedReader br = new BufferedReader(reader); // 建立一个对象,它把文件内容转成计算机能读懂的语言String line;//网友推荐更加简洁的写法while ((line = br.readLine()) != null) {result+=line;}return result;}public static List<String> getStrContainData(String str, String start, String end){List<String> result = new ArrayList<>();String regex = start + "(.*?)" + end;Pattern pattern = Pattern.compile(regex);Matcher matcher = pattern.matcher(str);while(matcher.find()){String key = matcher.group(1);if(!key.contains(start) && !key.contains(end)){result.add(key);}}return result;}
}

最后的结果我转成了json格式

{"blackName":"江维杰","blacklevel":"九段","dict":"中国","manualid":0,"playList":[{"color":"black","step":1,"x":15,"y":3},{"color":"white","step":2,"x":3,"y":15},{"color":"black","step":3,"x":16,"y":15},{"color":"white","step":4,"x":3,"y":3},{"color":"black","step":5,"x":13,"y":15},{"color":"white","step":6,"x":16,"y":2},{"color":"black","step":7,"x":16,"y":3},{"color":"white","step":8,"x":15,"y":2},{"color":"black","step":9,"x":13,"y":2},{"color":"white","step":10,"x":14,"y":2},{"color":"black","step":11,"x":14,"y":3},{"color":"white","step":12,"x":13,"y":1},{"color":"black","step":13,"x":5,"y":16},{"color":"white","step":14,"x":7,"y":16},{"color":"black","step":15,"x":2,"y":2},{"color":"white","step":16,"x":2,"y":3},{"color":"black","step":17,"x":3,"y":2},{"color":"white","step":18,"x":4,"y":2},{"color":"black","step":19,"x":4,"y":1},{"color":"white","step":20,"x":5,"y":1},{"color":"black","step":21,"x":5,"y":2},{"color":"white","step":22,"x":4,"y":3},{"color":"black","step":23,"x":6,"y":1},{"color":"white","step":24,"x":3,"y":1},{"color":"black","step":25,"x":5,"y":0},{"color":"white","step":26,"x":2,"y":1},{"color":"black","step":27,"x":5,"y":14},{"color":"white","step":28,"x":3,"y":12},{"color":"black","step":29,"x":9,"y":16},{"color":"white","step":30,"x":9,"y":15},{"color":"black","step":31,"x":10,"y":15},{"color":"white","step":32,"x":8,"y":15},{"color":"black","step":33,"x":10,"y":14},{"color":"white","step":34,"x":10,"y":16},{"color":"black","step":35,"x":10,"y":17},{"color":"white","step":36,"x":11,"y":16},{"color":"black","step":37,"x":8,"y":17},{"color":"white","step":38,"x":15,"y":15},{"color":"black","step":39,"x":15,"y":14},{"color":"white","step":40,"x":16,"y":14},{"color":"black","step":41,"x":15,"y":16},{"color":"white","step":42,"x":7,"y":17},{"color":"black","step":43,"x":12,"y":16},{"color":"white","step":44,"x":8,"y":13},{"color":"black","step":45,"x":1,"y":2},{"color":"white","step":46,"x":1,"y":1},{"color":"black","step":47,"x":4,"y":17},{"color":"white","step":48,"x":3,"y":16},{"color":"black","step":49,"x":6,"y":13},{"color":"white","step":50,"x":8,"y":11},{"color":"black","step":51,"x":6,"y":11},{"color":"white","step":52,"x":3,"y":10},{"color":"black","step":53,"x":2,"y":17},{"color":"white","step":54,"x":3,"y":17},{"color":"black","step":55,"x":3,"y":18},{"color":"white","step":56,"x":1,"y":16},{"color":"black","step":57,"x":4,"y":11},{"color":"white","step":58,"x":3,"y":11},{"color":"black","step":59,"x":4,"y":13},{"color":"white","step":60,"x":8,"y":9},{"color":"black","step":61,"x":5,"y":9},{"color":"white","step":62,"x":3,"y":8},{"color":"black","step":63,"x":16,"y":13},{"color":"white","step":64,"x":5,"y":7},{"color":"black","step":65,"x":9,"y":10},{"color":"white","step":66,"x":8,"y":10},{"color":"black","step":67,"x":8,"y":12},{"color":"white","step":68,"x":9,"y":12},{"color":"black","step":69,"x":7,"y":12},{"color":"white","step":70,"x":9,"y":14},{"color":"black","step":71,"x":9,"y":11},{"color":"white","step":72,"x":10,"y":13},{"color":"black","step":73,"x":11,"y":15},{"color":"white","step":74,"x":10,"y":11},{"color":"black","step":75,"x":10,"y":10},{"color":"white","step":76,"x":11,"y":11},{"color":"black","step":77,"x":11,"y":10},{"color":"white","step":78,"x":11,"y":14},{"color":"black","step":79,"x":11,"y":17},{"color":"white","step":80,"x":12,"y":10},{"color":"black","step":81,"x":10,"y":8},{"color":"white","step":82,"x":13,"y":11},{"color":"black","step":83,"x":7,"y":8},{"color":"white","step":84,"x":13,"y":8},{"color":"black","step":85,"x":12,"y":12},{"color":"white","step":86,"x":12,"y":11},{"color":"black","step":87,"x":9,"y":7},{"color":"white","step":88,"x":12,"y":2},{"color":"black","step":89,"x":13,"y":3},{"color":"white","step":90,"x":17,"y":2},{"color":"black","step":91,"x":15,"y":8},{"color":"white","step":92,"x":15,"y":10},{"color":"black","step":93,"x":4,"y":5},{"color":"white","step":94,"x":5,"y":3},{"color":"black","step":95,"x":11,"y":12},{"color":"white","step":96,"x":10,"y":12},{"color":"black","step":97,"x":2,"y":6},{"color":"white","step":98,"x":5,"y":5},{"color":"black","step":99,"x":2,"y":14},{"color":"white","step":100,"x":2,"y":13},{"color":"black","step":101,"x":2,"y":15},{"color":"white","step":102,"x":2,"y":16},{"color":"black","step":103,"x":3,"y":14},{"color":"white","step":104,"x":1,"y":14},{"color":"black","step":105,"x":1,"y":10},{"color":"white","step":106,"x":1,"y":11},{"color":"black","step":107,"x":2,"y":8},{"color":"white","step":108,"x":6,"y":9},{"color":"black","step":109,"x":3,"y":7},{"color":"white","step":110,"x":6,"y":8},{"color":"black","step":111,"x":3,"y":9},{"color":"white","step":112,"x":4,"y":8},{"color":"black","step":113,"x":4,"y":9},{"color":"white","step":114,"x":2,"y":10},{"color":"black","step":115,"x":7,"y":7},{"color":"white","step":116,"x":6,"y":10},{"color":"black","step":117,"x":5,"y":6},{"color":"white","step":118,"x":4,"y":6},{"color":"black","step":119,"x":6,"y":6},{"color":"white","step":120,"x":4,"y":7},{"color":"black","step":121,"x":6,"y":7},{"color":"white","step":122,"x":5,"y":8},{"color":"black","step":123,"x":3,"y":5},{"color":"white","step":124,"x":3,"y":6},{"color":"black","step":125,"x":2,"y":7},{"color":"white","step":126,"x":2,"y":5},{"color":"black","step":127,"x":1,"y":5},{"color":"white","step":128,"x":2,"y":4},{"color":"black","step":129,"x":5,"y":4},{"color":"white","step":130,"x":6,"y":5},{"color":"black","step":131,"x":6,"y":4},{"color":"white","step":132,"x":7,"y":5},{"color":"black","step":133,"x":4,"y":4},{"color":"white","step":134,"x":8,"y":6},{"color":"black","step":135,"x":7,"y":9},{"color":"white","step":136,"x":7,"y":10},{"color":"black","step":137,"x":8,"y":8},{"color":"white","step":138,"x":7,"y":2},{"color":"black","step":139,"x":6,"y":3},{"color":"white","step":140,"x":6,"y":2},{"color":"black","step":141,"x":7,"y":3},{"color":"white","step":142,"x":8,"y":3},{"color":"black","step":143,"x":8,"y":2},{"color":"white","step":144,"x":5,"y":1},{"color":"black","step":145,"x":8,"y":4},{"color":"white","step":146,"x":9,"y":3},{"color":"black","step":147,"x":5,"y":2},{"color":"white","step":148,"x":7,"y":1},{"color":"black","step":149,"x":7,"y":4},{"color":"white","step":150,"x":9,"y":4},{"color":"black","step":151,"x":8,"y":5},{"color":"white","step":152,"x":9,"y":5},{"color":"black","step":153,"x":7,"y":6},{"color":"white","step":154,"x":13,"y":6},{"color":"black","step":155,"x":16,"y":6},{"color":"white","step":156,"x":16,"y":9},{"color":"black","step":157,"x":12,"y":3},{"color":"white","step":158,"x":11,"y":2},{"color":"black","step":159,"x":14,"y":1},{"color":"white","step":160,"x":12,"y":1},{"color":"black","step":161,"x":17,"y":3}],"result":"黑中盘胜","tiemu":7.5,"time":"2019-05-28","title":"第10届中国围棋龙星战半决赛","whiteName":"辜梓豪","whitelevel":"九段"}

以上是楼主的简单实现,有更简单的方法,欢迎评论

java解析sgf格式文件简单实现相关推荐

  1. java解析pdf格式文件获取文本内容

    思路:先将pdf按照页数分割成图片,在将分割的图片做图片识别,提取文字,最后将提取到的文字解析或者保存到txt文件. 图片识别我使用的是百度开发者中心提供的 图片识别接口,我在上一篇文章中有详细说明, ...

  2. 第8.1.2解析mht格式文件

    有人建议改造一下mhtifier.py就可以解析mht格式文件,它的示例没有告诉我,怎么验证.而且我改造也失败了,可能是我的水平有限. Python :解析 word 文档(前程无忧简历),这篇文章的 ...

  3. IDEA Java解析GeoJson.json文件

    IDEA Java解析GeoJson.json文件 一.遇到的问题 1. 无法导入成功 2. org.geotools.StyleFactory is not an ImageIO SPI class ...

  4. Golang解析yaml格式文件

    关注公众号 风色年代(itfantasycc) 300G微服务资料等你拿! 作者:会飞的鲶鱼 链接:Golang解析yaml格式文件 - 简书 來源:简书 简书著作权归作者所有,任何形式的转载都请联系 ...

  5. JavaScript解析json格式数据简单示例

    JavaScript解析json格式数据简单示例 本文通过for循环来获取json结点数据,需要的朋友可以参考以下这串json数据用来存储预加载的图片路径: 代码如下: var imgData = [ ...

  6. java解析zip格式压缩包

    java解析zip格式压缩包 做项目时遇到需要将zip格式的压缩包解析里面的图片 将里面的图片保存到文件夹 并且保存到数据库中关联起来 在上传时判断是否为zip格式的文件 @RequestMappin ...

  7. java 导出csv 格式,java导出csv格式文件的方法

    这篇文章主要为大家详细介绍了java导出csv格式文件的方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 导出csv格式文件的本质是导出以逗号为分隔的文本数据 imp ...

  8. java 解析日期格式_日期/时间格式/解析,Java 8样式

    java 解析日期格式 自Java 几乎 开始以来,Java开发人员就通过java.util.Date类(自JDK 1.0起)和java.util.Calendar类(自JDK 1.1起 )来处理日期 ...

  9. java解析webp格式图片宽高;java解析webp图片转png格式

    java解析webp格式图片宽高:java解析webp图片转png格式 package 你的包名:***.***.***.***;import java.io.FileInputStream; imp ...

最新文章

  1. 【RocketMQ工作原理】订阅关系的一致性
  2. 上帝给你关闭一道门,就会为你打开一扇窗,反推。
  3. input获取焦点软键盘弹出影响定位
  4. android4.0.3源码之鼠标光标绘制简略版
  5. 基于Web的质量和测试度量指标
  6. CRSLab:可能是最适合你的对话推荐系统开源库
  7. GridView应用整理
  8. 来了就不会空着手回去.
  9. 【莓控】黑莓GOOGLE MAPS(GPS软件)-转贴
  10. Matplotlib Line2D设置
  11. Bing 和 Cortana 源码遭泄露,网友嘲讽:其实没人想要
  12. [C#]方法示例:判断是否闰年
  13. 利用域策略设置域用户IE主页设置
  14. 【python】语句
  15. Gramine(原graphene-sgx)软件栈
  16. 2、slf4j绑定JUL(桥接模式)
  17. 桥接路由器总是掉线_TP-LINK路由器桥接不稳定的解决方法
  18. JAVA怎么给扇形加边框_PS怎么制作扇形边框 扇面边框教程
  19. 寒江独钓:Windows内核安全编程(china-pub到货首发)
  20. 听说有人谋求稳定的工作?

热门文章

  1. $.parser.parse()是什么意思
  2. 同济大学计算机专业录取分数线,同济大学全国各省各专业录取分数线汇总
  3. 002--使用代理工具实现纵向渗透
  4. 计算机专业的就业方向有哪些呢?
  5. 自动整理文件夹(Droplt使用教程)
  6. 2022年,消费品企业应该选择什么样的会员系统?
  7. 0730Python总结-正则表达式
  8. 战略采购的六个基本步骤
  9. 教你如何在网站上挂qq聊天功能
  10. 【逆变器知识总结1】同步调制与异步调制