Compare commits

..

20 Commits
0.3.2 ... 0.3.3

Author SHA1 Message Date
6bd37f384c fix 2019-05-18 22:14:08 +08:00
2c61fd3a3f add doujinshi folder formatter 2019-05-18 22:13:23 +08:00
cf4291d3c2 new line 2019-05-18 22:01:29 +08:00
450e3689a0 fix 2019-05-18 22:00:33 +08:00
b5deca2704 fix 2019-05-18 21:57:43 +08:00
57dc4a58b9 remove Options block 2019-05-18 21:56:59 +08:00
1e1d03064b readme 2019-05-18 21:56:35 +08:00
40a98881c6 add some shortcut options 2019-05-18 21:53:40 +08:00
a7848c3cd0 fix bug 2019-05-18 21:52:36 +08:00
5df58780d9 add delay #55 2019-05-18 21:51:38 +08:00
56dace81f1 remove readme.md 2019-05-18 20:31:18 +08:00
086e469275 Update README.rst 2019-05-18 20:27:08 +08:00
1f76a8a70e Update README.rst 2019-05-18 20:24:49 +08:00
5d294212e6 Update README.rst 2019-05-18 20:24:15 +08:00
ef274a672b Update README.rst 2019-05-18 20:23:19 +08:00
795f80752f Update README.rst 2019-05-18 20:22:55 +08:00
53c23bb6dc Update README.rst 2019-05-18 20:07:45 +08:00
8d5f12292c update rst 2019-05-18 20:06:10 +08:00
f3141d5726 add rst 2019-05-18 20:04:16 +08:00
475e4db9af 0.3.2 #54 2019-05-18 19:47:04 +08:00
9 changed files with 226 additions and 115 deletions

View File

@ -1,84 +0,0 @@
nhentai
=======
_ _ _ _
_ __ | | | | ___ _ __ | |_ __ _(_)
| '_ \| |_| |/ _ \ '_ \| __/ _` | |
| | | | _ | __/ | | | || (_| | |
|_| |_|_| |_|\___|_| |_|\__\__,_|_|
あなたも変態。 いいね?
[![Build Status](https://travis-ci.org/RicterZ/nhentai.svg?branch=master)](https://travis-ci.org/RicterZ/nhentai) ![nhentai PyPI Downloads](https://img.shields.io/pypi/dm/nhentai.svg) [![license](https://img.shields.io/cocoapods/l/AFNetworking.svg)](https://github.com/RicterZ/nhentai/blob/master/LICENSE)
nHentai is a CLI tool for downloading doujinshi from [nhentai.net](http://nhentai.net).
### Installation
git clone https://github.com/RicterZ/nhentai
cd nhentai
python setup.py install
### Installation (Gentoo)
layman -fa glicOne
sudo emerge net-misc/nhentai
### Usage
**IMPORTANT**: To bypass the nhentai frequency limit, you should use `--login` option to log into nhentai.net.
*The default download folder will be the path where you run the command (CLI path).*
Download specified doujinshi:
```bash
nhentai --id=123855,123866
```
Download doujinshi with ids specified in a file:
```bash
nhentai --file=doujinshi.txt
```
Search a keyword and download the first page:
```bash
nhentai --search="tomori" --page=1 --download
```
Download your favourite doujinshi (login required):
```bash
nhentai --login "username:password" --download
```
Download by tag name:
```bash
nhentai --tag lolicon --download
```
### Options
+ `-t, --thread`: Download threads, max: 10
+ `--output`:Output dir of saving doujinshi
+ `--tag`:Download by tag name
+ `--timeout`: Timeout of downloading each image
+ `--proxy`: Use proxy, example: http://127.0.0.1:8080/
+ `--login`: username:password pair of your nhentai account
+ `--nohtml`: Do not generate HTML
+ `--cbz`: Generate Comic Book CBZ File
### nHentai Mirror
If you want to use a mirror, you should set up a reverse proxy of `nhentai.net` and `i.nhentai.net`.
For example:
i.h.loli.club -> i.nhentai.net
h.loli.club -> nhentai.net
Set `NHENTAI` env var to your nhentai mirror.
```bash
NHENTAI=http://h.loli.club nhentai --id 123456
```
![](./images/search.png)
![](./images/download.png)
![](./images/viewer.png)
### あなたも変態
![](./images/image.jpg)

186
README.rst Normal file
View File

@ -0,0 +1,186 @@
nhentai
=======
.. code-block::
_ _ _ _
_ __ | | | | ___ _ __ | |_ __ _(_)
| '_ \| |_| |/ _ \ '_ \| __/ _` | |
| | | | _ | __/ | | | || (_| | |
|_| |_|_| |_|\___|_| |_|\__\__,_|_|
あなたも変態。 いいね?
|travis|
|pypi|
|license|
nHentai is a CLI tool for downloading doujinshi from <http://nhentai.net>
============
Installation
============
.. code-block::
git clone https://github.com/RicterZ/nhentai
cd nhentai
python setup.py install
=====================
Installation (Gentoo)
=====================
.. code-block::
layman -fa glicOne
sudo emerge net-misc/nhentai
=====
Usage
=====
**IMPORTANT**: To bypass the nhentai frequency limit, you should use `--cookie` option to store your cookie.
*The default download folder will be the path where you run the command (CLI path).*
Set your nhentai cookie against captcha:
.. code-block:: bash
nhentai --cookie 'YOUR COOKIE FROM nhentai.net'
Download specified doujinshi:
.. code-block:: bash
nhentai --id=123855,123866
Download doujinshi with ids specified in a file (doujinshi ids split by line):
.. code-block:: bash
nhentai --file=doujinshi.txt
Search a keyword and download the first page:
.. code-block:: bash
nhentai --search="tomori" --page=1 --download
Download by tag name:
.. code-block:: bash
nhentai --tag lolicon --download --page=2
Download your favorites with delay:
.. code-block:: bash
nhentai --favorites --download --delay 1
Format output doujinshi folder name:
.. code-block:: bash
nhentai --id 261100 --format '[%i]%s'
Supported doujinshi folder formatter:
- %i: Doujinshi id
- %t: Doujinshi name
- %s: Doujinshi subtitle (translated name)
- %a: Doujinshi authors' name
Other options:
.. code-block::
Options:
# Operation options
-h, --help show this help message and exit
-D, --download download doujinshi (for search results)
-S, --show just show the doujinshi information
# Doujinshi options
--id=ID doujinshi ids set, e.g. 1,2,3
-s KEYWORD, --search=KEYWORD
search doujinshi by keyword
--tag=TAG download doujinshi by tag
-F, --favorites list or download your favorites.
# Multi-page options
--page=PAGE page number of search results
--max-page=MAX_PAGE The max page when recursive download tagged doujinshi
# Download options
-o OUTPUT_DIR, --output=OUTPUT_DIR
output dir
-t THREADS, --threads=THREADS
thread count for downloading doujinshi
-T TIMEOUT, --timeout=TIMEOUT
timeout for downloading doujinshi
-d DELAY, --delay=DELAY
slow down between downloading every doujinshi
-p PROXY, --proxy=PROXY
uses a proxy, for example: http://127.0.0.1:1080
-f FILE, --file=FILE read gallery IDs from file.
--format=NAME_FORMAT format the saved folder name
# Generating options
--html generate a html viewer at current directory
--no-html don't generate HTML after downloading
-C, --cbz generate Comic Book CBZ File
--rm-origin-dir remove downloaded doujinshi dir when generated CBZ
file.
# nHentai options
--cookie=COOKIE set cookie of nhentai to bypass Google recaptcha
==============
nHentai Mirror
==============
If you want to use a mirror, you should set up a reverse proxy of `nhentai.net` and `i.nhentai.net`.
For example:
.. code-block::
i.h.loli.club -> i.nhentai.net
h.loli.club -> nhentai.net
Set `NHENTAI` env var to your nhentai mirror.
.. code-block:: bash
NHENTAI=http://h.loli.club nhentai --id 123456
.. image:: ./images/search.png?raw=true
:alt: nhentai
:align: center
.. image:: ./images/download.png?raw=true
:alt: nhentai
:align: center
.. image:: ./images/viewer.png?raw=true
:alt: nhentai
:align: center
============
あなたも変態
============
.. image:: ./images/image.jpg?raw=true
:alt: nhentai
:align: center
.. |travis| image:: https://travis-ci.org/RicterZ/nhentai.svg?branch=master
:target: https://travis-ci.org/RicterZ/nhentai
.. |pypi| image:: https://img.shields.io/pypi/dm/nhentai.svg
:target: https://pypi.org/project/nhentai/
.. |license| image:: https://img.shields.io/github/license/ricterz/nhentai.svg
:target: https://github.com/RicterZ/nhentai/blob/master/LICENSE

View File

@ -1,3 +1,3 @@
__version__ = '0.3.1'
__version__ = '0.3.2'
__author__ = 'RicterZ'
__email__ = 'ricterzheng@gmail.com'

View File

@ -42,13 +42,13 @@ def cmd_parser():
'\n\nEnvironment Variable:\n'
' NHENTAI nhentai mirror url')
# operation options
parser.add_option('--download', dest='is_download', action='store_true',
parser.add_option('--download', '-D', dest='is_download', action='store_true',
help='download doujinshi (for search results)')
parser.add_option('--show', dest='is_show', action='store_true', help='just show the doujinshi information')
parser.add_option('--show', '-S', dest='is_show', action='store_true', help='just show the doujinshi information')
# doujinshi options
parser.add_option('--id', type='string', dest='id', action='store', help='doujinshi ids set, e.g. 1,2,3')
parser.add_option('--search', type='string', dest='keyword', action='store', help='search doujinshi by keyword')
parser.add_option('--search', '-s', type='string', dest='keyword', action='store', help='search doujinshi by keyword')
parser.add_option('--tag', type='string', dest='tag', action='store', help='download doujinshi by tag')
parser.add_option('--favorites', '-F', action='store_true', dest='favorites',
help='list or download your favorites.')
@ -60,22 +60,26 @@ def cmd_parser():
help='The max page when recursive download tagged doujinshi')
# download options
parser.add_option('--output', type='string', dest='output_dir', action='store', default='',
parser.add_option('--output', '-o', type='string', dest='output_dir', action='store', default='',
help='output dir')
parser.add_option('--threads', '-t', type='int', dest='threads', action='store', default=5,
help='thread count for downloading doujinshi')
parser.add_option('--timeout', type='int', dest='timeout', action='store', default=30,
parser.add_option('--timeout', '-T', type='int', dest='timeout', action='store', default=30,
help='timeout for downloading doujinshi')
parser.add_option('--proxy', type='string', dest='proxy', action='store', default='',
parser.add_option('--delay', '-d', type='int', dest='delay', action='store', default=0,
help='slow down between downloading every doujinshi')
parser.add_option('--proxy', '-p', type='string', dest='proxy', action='store', default='',
help='uses a proxy, for example: http://127.0.0.1:1080')
parser.add_option('--file', '-f', type='string', dest='file', action='store', help='read gallery IDs from file.')
parser.add_option('--format', type='string', dest='name_format', action='store',
help='format the saved folder name', default='[%i][%a][%t]')
# generate options
parser.add_option('--html', dest='html_viewer', action='store_true',
help='generate a html viewer at current directory')
parser.add_option('--nohtml', dest='is_nohtml', action='store_true',
help='don\'t generate HTML')
parser.add_option('--cbz', dest='is_cbz', action='store_true',
parser.add_option('--no-html', dest='is_nohtml', action='store_true',
help='don\'t generate HTML after downloading')
parser.add_option('--cbz', '-C', dest='is_cbz', action='store_true',
help='generate Comic Book CBZ File')
parser.add_option('--rm-origin-dir', dest='rm_origin_dir', action='store_true', default=False,
help='remove downloaded doujinshi dir when generated CBZ file.')

View File

@ -3,6 +3,7 @@
from __future__ import unicode_literals, print_function
import signal
import platform
import time
from nhentai.cmdline import cmd_parser, banner
from nhentai.parser import doujinshi_parser, search_parser, print_doujinshi, favorites_parser, tag_parser, login
@ -25,36 +26,33 @@ def main():
if not options.is_download:
logger.warning('You do not specify --download option')
for doujinshi_info in favorites_parser():
doujinshi_list.append(Doujinshi(**doujinshi_info))
doujinshi_ids = favorites_parser()
if not options.is_download:
print_doujinshi([{'id': i.id, 'title': i.name} for i in doujinshi_list])
exit(0)
if options.tag:
elif options.tag:
doujinshis = tag_parser(options.tag, max_page=options.max_page)
print_doujinshi(doujinshis)
if options.is_download and doujinshis:
doujinshi_ids = map(lambda d: d['id'], doujinshis)
if options.keyword:
elif options.keyword:
doujinshis = search_parser(options.keyword, options.page)
print_doujinshi(doujinshis)
if options.is_download:
doujinshi_ids = map(lambda d: d['id'], doujinshis)
if not doujinshi_ids:
elif not doujinshi_ids:
doujinshi_ids = options.id
if doujinshi_ids:
for id_ in doujinshi_ids:
if options.delay:
time.sleep(options.delay)
doujinshi_info = doujinshi_parser(id_)
doujinshi_list.append(Doujinshi(**doujinshi_info))
doujinshi_list.append(Doujinshi(name_format=options.name_format, **doujinshi_info))
if not options.is_show:
downloader = Downloader(path=options.output_dir,
thread=options.threads, timeout=options.timeout)
thread=options.threads, timeout=options.timeout, delay=options.delay)
for doujinshi in doujinshi_list:
doujinshi.downloader = downloader

View File

@ -27,7 +27,7 @@ class DoujinshiInfo(dict):
class Doujinshi(object):
def __init__(self, name=None, id=None, img_id=None, ext='', pages=0, **kwargs):
def __init__(self, name=None, id=None, img_id=None, ext='', pages=0, name_format='[%i][%a][%t]', **kwargs):
self.name = name
self.id = id
self.img_id = img_id
@ -36,7 +36,12 @@ class Doujinshi(object):
self.downloader = None
self.url = '%s/%d' % (DETAIL_URL, self.id)
self.info = DoujinshiInfo(**kwargs)
self.filename = format_filename('[%s][%s][%s]' % (self.id, self.info.artist, self.name))
name_format = name_format.replace('%i', str(self.id))
name_format = name_format.replace('%a', self.info.artists)
name_format = name_format.replace('%t', self.name)
name_format = name_format.replace('%s', self.info.subtitle)
self.filename = name_format
def __repr__(self):
return '<Doujinshi: {0}>'.format(self.name)
@ -46,7 +51,7 @@ class Doujinshi(object):
["Doujinshi", self.name],
["Subtitle", self.info.subtitle],
["Characters", self.info.character],
["Authors", self.info.artist],
["Authors", self.info.artists],
["Language", self.info.language],
["Tags", self.info.tags],
["URL", self.url],

View File

@ -4,6 +4,8 @@ from future.builtins import str as text
import os
import requests
import threadpool
import time
try:
from urllib.parse import urlparse
except ImportError:
@ -23,7 +25,7 @@ class NhentaiImageNotExistException(Exception):
class Downloader(Singleton):
def __init__(self, path='', thread=1, timeout=30):
def __init__(self, path='', thread=1, timeout=30, delay=0):
if not isinstance(thread, (int, )) or thread < 1 or thread > 15:
raise ValueError('Invalid threads count')
self.path = str(path)
@ -31,8 +33,11 @@ class Downloader(Singleton):
self.threads = []
self.thread_pool = None
self.timeout = timeout
self.delay = delay
def _download(self, url, folder='', filename='', retried=0):
if self.delay:
time.sleep(self.delay)
logger.info('Starting to download {0} ...'.format(url))
filename = filename if filename else os.path.basename(urlparse(url).path)
base_filename, extension = os.path.splitext(filename)

View File

@ -97,9 +97,7 @@ def favorites_parser():
logger.info('Getting doujinshi ids of page %d' % page)
resp = request('get', constant.FAV_URL + '?page=%d' % page).text
ids = doujinshi_id.findall(resp)
for i in ids:
ret.append(doujinshi_parser(i))
ret.extend(ids)
except Exception as e:
logger.error('Error: %s, continue', str(e))

View File

@ -11,8 +11,7 @@ with open('requirements.txt') as f:
def long_description():
with codecs.open('README.md', 'rb') as f:
if sys.version_info >= (3, 0, 0):
with codecs.open('README.rst', 'r') as f:
return str(f.read())
setup(