public static String parseRankingList(InputStream content, List<Ranking> list)
      throws ParseException {
    String body = Parser.read(content);
    Matcher m = RE_RANKING_TITLE.matcher(body);
    int last = m.regionEnd();
    for (MatchResult r = m.find() ? m.toMatchResult() : null; r != null; ) {
      String id = r.group(1);
      String title = r.group(2);
      int start = r.end();

      m = m.usePattern(RE_RANKING_TITLE);
      m.region(start, last);
      if (m.find()) {
        r = m.toMatchResult();
        m.region(start, r.start());
      } else {
        r = null;
      }

      for (int rank = 3; rank > 1; --rank) {
        Ranking entry = parseRankIn(m, DIFFICULTIES[rank]);
        if (entry != null) {
          entry.id = id;
          entry.title = title;
          entry.rank = rank;
          entry.rival_code = null;
          list.add(entry);
        }
      }
    }

    m = m.usePattern(Parser.RE_NEXT);
    return m.find() ? m.group(1) : null;
  }
 public static String[] parseVoice(InputStream content) throws ParseException {
   String body = Parser.read(content);
   Matcher m = RE_VOICE.matcher(body);
   if (!m.find()) throw new ParseException();
   String voice1 = m.group(2);
   String voice2 = m.find() ? m.group(2) : null;
   return new String[] {voice1, voice2};
 }
  public static String parseListPage(InputStream content, List<MusicInfo> list) {
    String body = Parser.read(content);
    Matcher m = RE_MUSIC_TITLE.matcher(body);
    while (m.find()) list.add(new MusicInfo(m.group(1), m.group(2)));

    m = m.usePattern(Parser.RE_NEXT);
    return m.find() ? m.group(1) : null;
  }
 public static void parseInfoPage(InputStream content, MusicInfo music) throws ParseException {
   String body = Parser.read(content);
   Pattern RE_COVERART =
       Pattern.compile(
           Pattern.quote(music.title) + "<br>\\s*\\[(.*)\\]\\s*<br>\\s*<img src=\"(.+?)\"");
   Matcher m = RE_COVERART.matcher(body);
   if (!m.find()) throw new ParseException();
   music.part = "ソロ".equals(m.group(1)) ? 1 : 2;
   music.coverart = m.group(2);
   for (int i = 0; i < DIFFICULTIES.length; ++i)
     music.records[i] = parseScore(m, DIFFICULTIES[i], music.records[i]);
 }
  public static String parsePlayHistory(InputStream content, List<String> ids, long[] params)
      throws ParseException {
    String body = Parser.read(content);
    Matcher m = RE_HISTORY.matcher(body);
    try {
      while (m.find()) {
        long playTime = HISTORY_DATE.parse(m.group(1)).getTime();
        if (playTime <= params[0]) return null;
        if (playTime > params[1]) params[1] = playTime;
        final String id = m.group(2);
        if (!ids.contains(id)) ids.add(id);
      }
    } catch (Exception e) {
      throw new ParseException(e);
    }

    m = m.usePattern(Parser.RE_NEXT);
    return m.find() ? m.group(1) : null;
  }