Exemple #1
0
def main(props=_libssw.Summary(), p_args=_argparse.Namespace, dmmparser=None):

    # モジュール呼び出しの場合継承したコマンドライン引数は無視
    argv = [props.url] if __name__ != '__main__' else _sys.argv[1:]
    args = _get_args(argv, p_args)

    # 作品情報
    summ = _libssw.Summary()

    if __name__ == '__main__':
        _verbose('args: ', args)
        if not args.url:
            # URLが渡されなかったときは標準入力から
            _verbose('Input from stdin...')

            data = _sys.stdin.readline().rstrip('\n')

            if not data:
                _emsg('E', 'URLを指定してください。')

            for key, data in zip(('url', 'title', 'pid', 'actress', 'number',
                                  'director', 'director', 'note'),
                                 data.split('\t')):
                if key == 'url':
                    summ[key] = data.split('?')[0]
                elif key == 'actess':
                    summ[key] = list(_libssw.parse_names(data))
                elif key == 'number':
                    summ[key] = int(data) if data else 0
                elif key == 'director':
                    summ[key] = _libssw.re_delim.split(data)
                elif key == 'note':
                    summ[key].append(data)
                else:
                    summ[key] = data

            _verbose('summ from stdin: ', summ.items())

        for attr in ('url', 'number', 'pid', 'subtitle'):
            if not summ[attr]:
                summ[attr] = getattr(args, attr)

        if not summ['actress'] and args.actress:
            actiter = _chain.from_iterable(
                map(_libssw.re_delim.split, args.actress))
            summ['actress'] = list(_libssw.parse_names(actiter))

    else:
        _verbose('props: ', props.items())
        _verbose('p_args: ', vars(p_args))

        summ.update(props)

    summ['link_label'] = getattr(args, 'label')
    summ['link_series'] = getattr(args, 'series')

    retrieval = getattr(p_args, 'retrieval',
                        'series' if args.as_series else 'find')
    service = getattr(p_args, 'service', None)
    series_guide = getattr(p_args, 'series_guide', True)

    if args.actress and args.actress[0].startswith('@@'):
        # ウィキテキストで直接指定
        rawpfmrs = args.actress[0][2:]
    else:
        rawpfmrs = ''

    # サービス未指定時の自動決定
    if not service:
        service = _libssw.resolve_service(summ['url'])
    _verbose('service resolved: ', service)

    if service == 'ama':
        # 動画(素人)の場合監督欄は出力しない。
        args.dir_col = False

    join_d = dict()
    _libssw.ret_joindata(join_d, args)

    if (args.join_tsv or args.join_wiki or args.join_html) and not len(join_d):
        _emsg('E', '--join-* オプションで読み込んだデータが0件でした。')

    # URLを開いて読み込む
    resp, he = _libssw.open_url(summ['url'], set_cookie='age_check_done=1')

    if resp.status == 404:
        # 404の時、空のエントリを作成(表形式のみ)して返す
        _emsg('I', 'ページが見つかりませんでした: ', summ['url'])
        if not summ['pid']:
            summ['pid'], summ['cid'] = _libssw.gen_pid(summ['url'])
        if p_args.cid_l:
            summ['url'] = ''
        else:
            if not summ['subtitle']:
                summ['subtitle'] = summ['title']
            summ['image_sm'], summ['image_lg'] = _build_image_url(
                service, summ['cid'])
        wktxt_t = _format_wikitext_t(summ, '', '/'.join(summ['director']),
                                     args.dir_col,
                                     _build_addcols(args.add_column,
                                                    summ), retrieval)
        _verbose('wktxt_t: ', wktxt_t)
        return False, resp.status, _ReturnVal(summ['release'],
                                              summ['pid'],
                                              summ['title'],
                                              summ['title_dmm'],
                                              summ['url'],
                                              summ['time'],
                                              summ('maker', 'maker_id'),
                                              summ('label', 'label_id'),
                                              summ('series', 'series_id'),
                                              summ['actress'],
                                              summ['link_label'],
                                              summ['link_series'],
                                              wktxt_a='',
                                              wktxt_t=wktxt_t)
    elif resp.status != 200:
        return False, resp.status, ('HTTP status', resp.status)

    # 構文ミスの修正
    # html = _libssw.sub(sub_href, html)

    # HTMLの解析
    if not dmmparser:
        dmmparser = _libssw.DMMParser(autostrip=args.autostrip,
                                      longtitle=args.longtitle,
                                      check_rental=args.check_rental,
                                      check_rltd=args.check_rltd)

    try:
        summ.update(dmmparser(he, service, summ, ignore_pfmrs=rawpfmrs))
    except _libssw.OmitTitleException as e:
        # 除外対象なので中止
        return False, 'Omitted', (e.key, e.word)

    _verbose('summ: ', summ.items())

    if dmmparser.data_replaced:
        service = dmmparser.data_replaced

    # joinデータがあったら補完
    if summ['url'] in join_d:
        summ.merge(join_d[summ['url']])

    if args.pid:
        summ['pid'] = args.pid

    # 画像がまだないときのリンク自動生成
    if not summ['image_lg']:
        summ['image_sm'], summ['image_lg'] = _build_image_url(
            service, summ['cid'])
        _verbose('image_sm: ', summ['image_sm'])
        _verbose('image_lg: ', summ['image_lg'])

    #
    # タイトルの調整
    #
    # 削除依頼対応
    for dl in _libssw.HIDE_NAMES_V:
        summ['title'] = summ['title'].replace(dl, '').strip()

    on_dmm = summ['title']
    # wiki構文と衝突する文字列の置き換え
    modified = _libssw.trans_wikisyntax(on_dmm)
    if _AUTOMODIFY:
        # ♥の代替文字列の置き換え
        modified = _libssw.sub(_sub_heart, modified)

    summ['title'] = modified
    if not summ['title_dmm'] and modified != on_dmm:
        summ['title_dmm'] = on_dmm
    _verbose('summ[title]: ', summ['title'])
    _verbose('summ[title_dmm]: ', summ['title_dmm'])

    # レーベル/シリーズ一覧へのリンク情報の設定
    if (not args.hide_list) and args.check_listpage:
        _resolve_pagelink(summ, args)
    _verbose('summ[link_label]: ', summ['link_label'])
    _verbose('summ[link_series]: ', summ['link_series'])

    if args.note:
        summ['note'] = list(_expansion(args.note, summ)) + summ['note']
    _verbose('note: ', summ['note'])

    add_column = _build_addcols(args.add_column, summ)
    _verbose('add column: ', add_column)

    # 出演者文字列の作成
    pfmrslk = ()
    if rawpfmrs:
        # ウィキテキスト
        pfmrslk = _libssw.re_linkpare.findall(rawpfmrs)
        pfmrsstr, pnum = rawpfmrs, len(pfmrslk)
    elif len(summ['actress']) < 2 and not summ['number'] and args.table == 0:
        # 女優ページ用のみ作成で出演者数が1人ならやらない
        pfmrsstr, pnum = '', 0
    else:
        pfmrsstr, pnum = _libssw.stringize_performers(summ['actress'],
                                                      summ['number'],
                                                      args.follow_rdr)

    # 監督文字列の作成
    dirstr = '/'.join(summ['director'])

    # table形式用副題の生成
    if retrieval == 'series':
        # シリーズ名が list_page にあってタイトルの先頭からシリーズ名と
        # 同じ文字列があれば落とす。
        # list_page に値がなければタイトルをそのまま入れる。
        if not summ['subtitle']:
            summ['subtitle'] = _re.sub(r'^{}[、。!?・…♥]*'.format(summ['series']),
                                       '',
                                       summ['title'],
                                       flags=_re.I).strip()

    elif not summ['subtitle']:
        # タイトルをそのまま副題に(表形式用)
        summ['subtitle'] = summ['title']
    _verbose('subtitle: ', summ['subtitle'])

    # 未取得情報のチェック
    if _VERBOSE:
        _check_missings(summ)

    # ウィキテキストの作成
    wikitext_a = _format_wikitext_a(summ, pnum, pfmrsstr,
                                    service) if args.table != 1 else ()
    wikitext_t = _format_wikitext_t(summ, pfmrsstr, dirstr, args.dir_col,
                                    add_column,
                                    retrieval) if args.table else ''

    if __name__ != '__main__':
        # モジュール呼び出しならタプルで返す。
        return True, summ['url'], _ReturnVal(
            summ['release'], summ['pid'], summ['title'],
            summ['title_dmm'], summ['url'], summ['time'],
            summ('maker', 'maker_id'), summ('label', 'label_id'),
            summ('series', 'series_id'), summ['actress'], summ['link_label'],
            summ['link_series'], wikitext_a, wikitext_t)
    else:
        # 書き出す
        output = ['']
        if wikitext_a:
            output.append(wikitext_a)

        if wikitext_t:
            output.append(wikitext_t)

        print(*output, sep='\n')

        if args.copy:
            _verbose('copy 2 clipboard')
            _libssw.copy2clipboard(''.join(output))

        if args.browser:
            # wikiのページを開く
            if args.table != 1:
                pages = pfmrslk or summ['actress']
                for a in pages:
                    _libssw.open_ssw(a[1] or a[0])
            if args.table:
                _libssw.open_ssw(summ['link_label'])
                _libssw.open_ssw(summ['link_series'])
Exemple #2
0
def select_allhiragana(ids, today, path, selfcheck):
    no_omits = libssw.gen_no_omits((0, 4))

    dmmparser = libssw.DMMParser(no_omits=no_omits,
                                 deeper=False,
                                 pass_bd=True,
                                 quiet=True)
    conn = sqlite3.connect(path)
    cur = conn.cursor()

    if ids:
        sql = 'select id,current,last_release from main ' \
              'where id in({}) '.format(','.join('?' * len(ids)))
        ph = [sql, ids]
    else:
        sql = 'select id,current,last_release from main ' \
              'where last_release is not null and ' \
              'retired is null and deleted is null '
        ph = []

    if not selfcheck:
        ayearago = str(today - timedelta(days=365))
        sql += 'and last_release > ?'
        ph.append(ayearago)

    print('sql:', sql, ', ph:', ph)

    for aid, name, last_release in filter(
            lambda n: not libssw.re_neghirag.search(n[1]) and len(n[1]) < 5,
            cur.execute(sql, ph)):
        verbose(aid, name)
        print(aid, name + ': ', end='')
        url = 'http://actress.dmm.co.jp/-/detail/=/actress_id={}/'.format(aid)
        verbose('url: ', url)

        if not selfcheck:
            # 自分でチェックしないなら名前を返すだけ
            print('({})'.format(last_release))
            yield name
            continue

        resp, he = libssw.open_url(url)

        while he is not None:
            info = he.find('.//td[@class="info_works1"]')
            if info is None:
                print('negative')
                continue

            for tr in info.getparent().getparent()[1:]:
                title = tr.find('td/a').text
                verbose('title: ', title)

                if tr[4].text == '---' and tr[6].text == '---':
                    verbose('Not DVD and Rental')
                    continue

                sale = tr[4].find('a')
                rental = tr[6].find('a')
                prod_url = sale.get('href') if sale is not None \
                           else rental.get('href')
                verbose('prod url: ', prod_url)
                cid = libssw.get_id(prod_url, cid=True)[0]

                if libssw.check_omit(title, cid, no_omits=no_omits):
                    continue

                b, status, values = dmm2ssw.main(
                    props=libssw.Summary(url=prod_url),
                    p_args=argparse.Namespace(fastest=True, hide_list=True),
                    dmmparser=dmmparser)
                if status in {'Omitted', 404}:
                    verbose('Omitted: status=', status, ', values=', values)
                    continue
                verbose('return from dmm2ssw: ', values)

                last_web = tr[7].text.strip()
                if last_release != last_web:
                    print('last_rel is different (db:{} <=> web:{}), '.format(
                        last_release, last_web),
                          end='')
                datelast = date(*map(int, last_web.split('-')))

                if (today - datelast).days < 366:

                    yield name
                    print('\033[1;33mpositive ({})\033[0m'.format(last_web))

                else:
                    print('negative ({})'.format(last_web))

                he = None
                break

            else:
                mu = he.get_element_by_id("mu").xpath('table[last()]//a')
                if len(mu) and mu[-1].text == '次へ':
                    resp, he = libssw.open_url(
                        BASEURL_ACT + mu[-1].get('href'))
                else:
                    print('negative')
                    break

    conn.close()
Exemple #3
0
def main(argv=None):

    args = get_args(argv or sys.argv[1:])

    make = MakeType(actress=args.table != 1, table=args.table)
    outfile = parse_outfile(args, make)
    verbose('outfile: ', outfile)

    ids = tuple(libssw.extr_ids(args.keyword, args.cid))
    verbose('ids: ', ids)

    if not args.retrieval:
        args.retrieval = libssw.extr_ids.retrieval
    emsg('I', '対象: {}'.format(args.retrieval))

    # -L, -K , -U 以外では --not-in-series は意味がない
    if args.retrieval not in {'label', 'maker', 'url'}:
        args.n_i_s = False
        verbose('force disabled n_i_s')

    if args.retrieval == 'actress':
        for i in filter(lambda i: i in libssw.HIDE_NAMES, ids):
            emsg('W', '削除依頼が出されている女優です: {}'.format(libssw.HIDE_NAMES[i]))
            ids.remove(i)

    # 除外対象
    no_omits = libssw.gen_no_omits(args.no_omit)
    verbose('non omit target: ', no_omits)

    # 品番生成用パターンのコンパイル
    sub_pid = (re.compile(args.pid_regex[0], re.I),
               args.pid_regex[1]) if args.pid_regex else None
    # 副題生成用パターンのコンパイル
    re_subtitle = (re.compile(args.subtitle_regex[0], re.I),
                   args.subtitle_regex[1]) if args.subtitle_regex else None

    # フィルター用パターン
    filter_id, fidattr = det_filterpatn(args)

    re_filter_pid_s = args.filter_pid_s and re.compile(args.filter_pid_s, re.I)
    re_filter_ttl = args.filter_title and re.compile(args.filter_title, re.I)

    # 作成開始品番
    key_id, key_type, kidattr = det_keyinfo(args)
    not_key_id = libssw.NotKeyIdYet(key_id, key_type, kidattr)

    listparser = libssw.DMMTitleListParser(no_omits=no_omits, patn_pid=sub_pid)
    seriesparser = libssw.DMMTitleListParser(patn_pid=sub_pid, show_info=False)

    # 作品情報取得用イテラブルの作成
    p_gen = make_pgen(args, ids, listparser, sub_pid, key_id, key_type,
                      kidattr)

    # 作品情報の取り込み
    # 新着順
    products = OrderedDict((u, p) for u, p in p_gen)
    emsg('I', '一覧取得完了')

    total = len(products)
    if not total:
        emsg('E', '検索結果は0件でした。')

    if not args.service:
        # TSVやウィキテキスト入力の場合の作品情報からサービス判定
        args.service = libssw.resolve_service(next(iter(products)))

    join_d = dict()
    libssw.ret_joindata(join_d, args)

    if (args.join_tsv or args.join_wiki or args.join_html) and not len(join_d):
        emsg('E', '--join-* オプションで読み込んだデータが0件でした。')

    if args.existings_html:
        # 既存の一覧ページから既出の作品情報の取得
        verbose('existings html')
        existings = set(k[0] for k in libssw.from_html(args.existings_html,
                                                       service=args.service))
        if not existings:
            emsg('E', '--existings-* オプションで読み込んだデータが0件でした。')
    else:
        existings = set()

    # 作品情報の作成
    verbose('Start building product info')
    if not VERBOSE and args.wikitext:
        print('作成中...', file=sys.stderr, flush=True)

    wikitexts = []
    title_list = []
    nis_series_names = set()  # 発見したシリーズ名 (n_i_s用)
    nis_series_urls = set()  # 発見したシリーズ一覧のURL (n_i_s用)
    rest = total
    omitted = listparser.omitted
    before = True if key_id else False

    dmmparser = libssw.DMMParser(no_omits=no_omits,
                                 patn_pid=sub_pid,
                                 start_date=args.start_date,
                                 start_pid_s=args.start_pid_s,
                                 filter_pid_s=re_filter_pid_s,
                                 pass_bd=args.pass_bd,
                                 n_i_s=args.n_i_s,
                                 longtitle=args.longtitle,
                                 check_rental=args.check_rental,
                                 check_rltd=args.check_rltd)

    if args.retrieval in {'maker', 'label', 'series'}:
        keyiter = libssw.sort_by_id(products)
    else:
        keyiter = iter(products)

    for url in keyiter:
        props = products[url]

        # 品番の生成
        if not props.pid:
            props.pid, props.cid = libssw.gen_pid(props.url, sub_pid)

        # 開始ID指定処理(--{start,last}-{p,c}id)
        if before:
            # 指定された品番が見つかるまでスキップ
            if not_key_id(getattr(props, kidattr)):
                emsg(
                    'I', '作品を除外しました: {}={} (id not met yet)'.format(
                        kidattr, getattr(props, kidattr)))
                omitted += 1
                rest -= 1
                continue
            else:
                before = False
                if key_type == 'start':
                    emsg('I',
                         '開始IDが見つかりました: {}'.format(getattr(props, kidattr)))
                else:
                    emsg('I',
                         '最終IDが見つかりました: {}'.format(getattr(props, kidattr)))
                    continue

        # 品番(pid/cid)が指定されたパターンにマッチしないものはスキップ処理(--filter-{p,c}id)
        if filter_id and not filter_id.search(getattr(props, fidattr)):
            emsg(
                'I',
                '作品を除外しました: {}={} (filtered)'.format(fidattr,
                                                     getattr(props, fidattr)))
            omitted += 1
            rest -= 1
            continue

        # 作品名が指定されたパターンにマッチしないものはスキップ処理(--filter-title)
        if args.filter_title and not re_filter_ttl.search(props.title):
            emsg('I', '作品を除外しました: title={} (filtered)'.format(props.title))
            omitted += 1
            rest -= 1
            continue

        # 一覧ページ内に既存の作品はスキップ(--existings-)
        if props.url in existings:
            emsg('I', '作品を除外しました: pid={} (already existent)'.format(props.pid))
            omitted += 1
            rest -= 1
            continue

        # 既知のシリーズ物のURLならスキップ (--not-in-series)
        if props.url in nis_series_urls:
            emsg('I',
                 '作品を除外しました: title="{}" (known series)'.format(props.title))
            omitted += 1
            rest -= 1
            continue

        if props.url in join_d:
            # joinデータがあるとデータをマージ
            props.merge(join_d[props.url])
            if args.hunter:
                props.title = join_d[props.url].title

        # 副題の生成
        if args.retrieval == 'series':
            # シリーズ一覧時のカスタムサブタイトル
            props.subtitle = libssw.sub(re_subtitle, props.title).strip() \
                if args.subtitle_regex else ''

        if args.wikitext:
            # ウィキテキストを作成
            libssw.inprogress('(残り {} 件/全 {} 件: 除外 {} 件)  '.format(
                rest, total, omitted))

            verbose('Call dmm2ssw')
            b, status, data = dmm2ssw.main(props, args, dmmparser)
            # 返り値:
            # b -> Bool
            # status -> url if b else http.status or 'Omitted'
            # data -> if b:
            #             ReturnVal(release,
            #                       pid,
            #                       title,
            #                       title_dmm,
            #                       url,
            #                       time,
            #                       ('maker', 'maker_id'),
            #                       ('label', 'label_id'),
            #                       ('series', 'series_id'),
            #                       wikitext_a,
            #                       wikitext_t)
            #         else:
            #             (key, hue) or empty ReturnVal (404)
            verbose('Return from dmm2ssw: {}, {}, {}'.format(b, status, data))

            if b:
                wikitexts.append(data)
            elif status == 404:
                wikitexts.append(data)
            else:
                emsg(
                    'I', '作品を除外しました: '
                    'cid={0}, reason=("{1[0]}", {1[1]})'.format(
                        props.cid, data))
                if args.n_i_s and data[0] == 'series':
                    # no-in-series用シリーズ作品先行取得
                    verbose('Retriving series products...')
                    nis_series_names.add(data[1].name)
                    priurls = libssw.join_priurls('series',
                                                  data[1].sid,
                                                  service=args.service)
                    nis_series_urls.update(
                        u[0] for u in libssw.from_dmm(seriesparser, priurls))
                omitted += 1

        else:
            # 一覧出力
            title_list.append(
                props.tsv('url', 'title', 'pid', 'actress', 'number',
                          'director', 'note'))

        rest -= 1

    if wikitexts:
        # ウィキテキストの書き出し
        verbose('Writing wikitext')

        # アーティクル名の決定
        article_name, article_header = det_articlename(args, ids, wikitexts,
                                                       listparser)
        verbose('article name: ', article_name)
        verbose('article header: ', repr(article_header))

        if not libssw.le80bytes(article_name):
            emsg('W', 'ページ名が80バイトを超えています')

        # ソート
        sortkeys = set_sortkeys(args.sort_key)
        for k in sortkeys:
            wikitexts.sort(key=attrgetter(k))

        if args.add_column:
            add_header = '|'.join(c.split(':')[0]
                                  for c in args.add_column) + '|'
            args.add_column = tuple(truncate_th(args.add_column))
        else:
            add_header = ''
        verbose('add header: {}\nadd column: {}'.format(
            add_header, args.add_column))

        if make.table and args.header:
            table_header = '|~{{}}|PHOTO|{}|ACTRESS|{}{}RELEASE|NOTE|'.format(
                'SUBTITLE' if args.retrieval == 'series' else 'TITLE',
                'DIRECTOR|' if args.dir_col else '', add_header)
        else:
            table_header = ''

        build_page = BuildPage(wikitexts, args.split, args.retrieval,
                               article_name, article_header, table_header)

        print(file=sys.stderr)

        result = '\n'.join(
            finalize(build_page, args.row, make, args.n_i_s, nis_series_names,
                     outfile))

        build_page.open_browser(args.browser)

        if args.copy:
            libssw.copy2clipboard(result)

    else:
        # タブ区切り一覧の書き出し

        fd = open(args.out, outfile.writemode) if args.out else sys.stdout

        print(*title_list, sep='\n', file=fd)

        if args.out:
            fd.close()
Exemple #4
0
def main():

    args = get_args()

    libssw.files_exists('r', *args.wikifiles)
    if args.out:
        if args.replace:
            writemode = 'w'
        else:
            libssw.files_exists('w', args.out)
            writemode = 'x'
    else:
        writemode = None

    g_actid = []
    seq = []
    contents = dict()
    release = dict()

    # 女優IDがURL渡しだったときの対処
    add_actid(g_actid, args.actress_id)

    # 除外対象
    no_omits = libssw.gen_no_omits(args.no_omit)
    verbose('non omit target: ', no_omits)

    # ウィキテキストの読み込み
    # 女優IDも取得
    for key, rdate, item in get_existing(g_actid, args.wikifiles):
        seq.append(key)
        contents[key] = item
        release[key] = rdate
        verbose('key: ', key)
        verbose('rdate: ', rdate)
        verbose('item: ', item)

    # 複数のIDがあった時にカンマで区切る
    aidstr = ','.join(g_actid)
    emsg('I', '女優ID: ', aidstr)

    listparser = libssw.DMMTitleListParser(no_omits)
    priurls = libssw.join_priurls('actress', aidstr)

    # Wikiにない作品情報の取り込み
    emsg('I', '作品一覧を取得中...')
    products = OrderedDict((u, p)
                           for u, p in libssw.from_dmm(listparser, priurls)
                           if u not in seq)
    emsg('I', '一覧取得完了')

    total = len(products)
    if not total:
        emsg('E', '検索結果は0件でした。')

    verbose('Start building product info')
    if not VERBOSE:
        print('作成中...', file=sys.stderr, flush=True)

    # 不足分のウィキテキストを作成
    current = seq[:]
    newitems = []
    rest = total
    omitted = 0

    dmmparser = libssw.DMMParser(no_omits)

    for url in products:
        props = products[url]
        verbose('props: ', props.items())

        props.pid, g_cid = libssw.gen_pid(props.url)

        libssw.inprogress('(残り {} 件/全 {} 件: 除外 {} 件)  '.format(
            rest, total, omitted))

        b, status, data = dmm2ssw.main(props=props,
                                       p_args=args,
                                       dmmparser=dmmparser)
        verbose('Return from dmm2ssw: {}, {}, {}'.format(b, status, data))

        if b:
            newitems.append(data)
        elif status == 404:
            emsg('I', 'ページが見つかりませんでした: url="{}"'.format(props.url))
            newitems.append(data)
        else:
            emsg(
                'I', 'ページを除外しました: '
                'cid={0}, reason=("{1[0]}", "{1[1]}")'.format(props.cid, data))
            omitted += 1
        rest -= 1
        verbose('rest: {} / total: {} / omitted: {}'.format(
            rest, total, omitted))

    # レンタル先行作品があった場合のためソート
    newitems.sort(key=itemgetter(0), reverse=True)

    # マージ
    i = -1
    for new in newitems:
        verbose('new: ', new)
        if new.url in seq:
            # レンタル版に変更にあったものの既存チェック
            continue

        for i, key in enumerate(seq[i + 1:], start=i + 1):
            # 時系列で途中のデータの挿入
            verbose('i, key: {}, {}'.format(i, key))
            if not key.isdecimal():
                verbose('new: {} > curr: {}'.format(
                    new.release.replace('/', '.'), release[key]))
                if new.release.replace('/', '.') > release[key]:
                    # 新規データの挿入
                    verbose('insert: {}, {}'.format(key, contents[key][1]))
                    seq.insert(i, new.url)
                    contents[new.url] = new.wktxt_a
                    release[new.url] = new.release
                    break
                elif '----' in contents[key]:
                    seq.append(new.url)
                    contents[new.url] = new.wktxt_a
                    release[new.url] = new.release
                    break
        else:
            # 残りのデータの追加
            seq.append(new.url)
            contents[new.url] = new.wktxt_a
            release[new.url] = new.release

    if args.diff:
        # 差分の出力
        libssw.show_diff(tuple(map(contents, current)),
                         tuple(map(contents, seq)), '追加前', '追加後')

    # 出力
    header = False
    i = 0
    fd = open(args.out, writemode) if args.out else sys.stdout
    while seq:
        key = seq.pop(0)
        if key.startswith('http://'):
            i += 1
            if args.split and not i % args.split:
                print('// {}'.format(i), file=fd)
        content = contents[key]
        if content.startswith('*'):
            header = True
        print(content, file=fd)
        if (not header or len(content) > 2) and seq:
            print(file=fd)
        header = False
    print()
    if args.out:
        fd.close()