Exemple #1
0
    def __call__(self, summ, args):
        _verbose('Processing list link')

        for attr in ('series', 'label', 'maker'):
            # 設定済みリンクは置き換えない
            if (attr == 'series' and summ['link_series']) or \
               (attr == 'label'  and summ['link_label'])  or \
               (attr == 'maker'  and summ['link_label']):
                continue

            list_type = ''
            list_page = summ[attr]

            # 検索対象が同じならレーベル一覧に統合
            if (attr != 'label' and (list_page == summ['label'])):
                continue

            if list_page:
                if list_page == '__HIDE__':
                    continue
                elif _libssw.le80bytes(list_page):
                    list_attr = attr
                    list_type = _libssw.RETLABEL[attr]
                else:
                    list_attr = ''
                    _emsg('W', _libssw.RETLABEL[attr],
                          '名が80バイトを超えているのでそのページは無いものとします: ', list_page)
                    continue

                _verbose('List type: {}, List page: {}'.format(
                    list_type, list_page))

                # wiki構文と衝突する文字列の置き換え
                list_page = _libssw.trans_wikisyntax(list_page)

                if (list_type, list_page) not in self._unknowns:

                    # Wiki上の実際の一覧ページを探し、見つかったらそれにする。
                    actuall = _libssw.check_actuallpage(
                        summ['url'], list_page, list_type, summ['pid'])
                    if actuall:
                        if attr == 'series':
                            summ['link_series'] = actuall
                        else:
                            summ['link_label'] = actuall
                            return
                    else:
                        _emsg('W', list_type, '一覧ページが見つかりません')
                        _emsg('W', list_type, ': ', list_page)
                        if __name__ != '__main__':
                            _emsg('I', 'タイトル: ', summ['title'],
                                  ' ({})'.format(summ['pid']))
                        self._unknowns.add((list_type, list_page))
Exemple #2
0
    def __call__(self, summ, retrieval, args):
        _verbose('Processing list link')

        list_type = ''

        for attr in ('series', 'label', 'maker'):

            list_page = summ[attr]

            if list_page:
                if list_page == '__HIDE__':
                    continue
                elif _libssw.le80bytes(list_page):
                    list_attr = attr
                    list_type = _libssw.RETLABEL[attr]
                    # break
                else:
                    _emsg('W', _libssw.RETLABEL[attr],
                          '名が80バイトを超えているのでそのページは無いものとします: ', list_page)

                _verbose('List type: {}, List page: {}'.format(
                    list_type, list_page))

                # SCOOP個別対応
                if list_page == 'SCOOP(スクープ)':
                    list_page = 'スクープ'

                # wiki構文と衝突する文字列の置き換え
                list_page = _libssw.trans_wikisyntax(list_page)

                if not args.check_listpage or \
                (list_attr == retrieval and args.table == 1):
                    _verbose('pass checking listpage')
                    return list_type, list_page

                if (list_type, list_page) not in self._unknowns:

                    # Wiki上の実際の一覧ページを探し、見つかったらそれにする。
                    actuall = _libssw.check_actuallpage(
                        summ['url'], list_page, list_type, summ['pid'])
                    if actuall:
                        list_page = actuall
                        return list_type, list_page
                    else:
                        _emsg('W', list_type, '一覧ページが見つからなくてもDMMのものを採用しません')
                        _emsg('W', list_type, ': ', list_page)
                        if __name__ != '__main__':
                            _emsg('I', 'タイトル: ', summ['title'],
                                  ' ({})'.format(summ['pid']))
                        self._unknowns.add((list_type, list_page))
        else:
            return '', ''
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(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)

    for attr, typ in (('series', 'シリーズ'), ('label', 'レーベル')):
        if getattr(args, attr):
            summ['list_type'] = typ
            summ['list_page'] = getattr(args, attr)

    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'])

    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, False,
                                     _build_addcols(args.add_column, summ))
        _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'),
                                              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,
                                      check_smm=args.smm)

    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 or summ['list_type']):
        summ['list_type'], summ['list_page'] = _resolve_listpage(
            summ, retrieval, args)
    if args.linklabel:
        summ['list_type'] = args.linklabel
    _verbose('summ[list_page]: ', summ['list_page'])

    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)

    # レーベル一覧での [[別ページ>]] への置き換えチェック
    # Wikiの制限で80バイトを超える場合は置き換えない
    diff_page = (series_guide and retrieval in ('label', 'maker')
                 and _libssw.le80bytes(summ['series']) and summ['series']
                 and summ['series'] != '__HIDE__')
    _verbose('diff_page: ', diff_page)

    # ウィキテキストの作成
    wikitext_a = _format_wikitext_a(summ, pnum,
                                    pfmrsstr) if args.table != 1 else ()
    wikitext_t = _format_wikitext_t(summ, pfmrsstr, dirstr, args.dir_col,
                                    diff_page,
                                    add_column) 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'),
                                             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['list_page'])