mirror of
				https://github.com/RicterZ/nhentai.git
				synced 2025-10-30 17:19:35 +01:00 
			
		
		
		
	Merge pull request #123 from Alocks/dev
--search fix, removed --tag commands
This commit is contained in:
		
							
								
								
									
										51
									
								
								README.rst
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								README.rst
									
									
									
									
									
								
							| @@ -79,53 +79,20 @@ Download doujinshi with ids specified in a file (doujinshi ids split by line): | ||||
|  | ||||
|     nhentai --file=doujinshi.txt | ||||
|  | ||||
| Set search default language | ||||
|  | ||||
| .. code-block:: bash | ||||
|  | ||||
|     nhentai --language=english | ||||
|  | ||||
| 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 by language: | ||||
|  | ||||
| .. code-block:: bash | ||||
|  | ||||
|     nhentai --language english --download --page=2 | ||||
|  | ||||
| Download by artist name: | ||||
|  | ||||
| .. code-block:: bash | ||||
|  | ||||
|     nhentai --artist henreader --download | ||||
|  | ||||
| Download by character name: | ||||
|  | ||||
| .. code-block:: bash | ||||
|  | ||||
|     nhentai --character "kuro von einsbern" --download | ||||
|  | ||||
| Download by parody name: | ||||
|  | ||||
| .. code-block:: bash | ||||
|  | ||||
|     nhentai --parody "the idolmaster" --download | ||||
|  | ||||
| Download by group name: | ||||
|  | ||||
| .. code-block:: bash | ||||
|  | ||||
|     nhentai --group clesta --download | ||||
|  | ||||
| Download using multiple tags (--tag, --character, --paordy and --group supported): | ||||
|  | ||||
| .. code-block:: bash | ||||
|  | ||||
|     nhentai --tag "lolicon, teasing" --artist "tamano kedama, atte nanakusa" | ||||
|     # you also can download by tags and multiple keywords | ||||
|     nhentai --search="tag:lolicon, artist:henreader, tag:full color" | ||||
|     nhentai --search="lolicon, henreader, full color" | ||||
|  | ||||
| Download your favorites with delay: | ||||
|  | ||||
|   | ||||
| @@ -38,7 +38,7 @@ def banner(): | ||||
| def cmd_parser(): | ||||
|     parser = OptionParser('\n  nhentai --search [keyword] --download' | ||||
|                           '\n  NHENTAI=http://h.loli.club nhentai --id [ID ...]' | ||||
|                           '\n  nhentai --file [filename]' | ||||
|                           '\n  nhentai --file [filename]'     | ||||
|                           '\n\nEnvironment Variable:\n' | ||||
|                           '  NHENTAI                 nhentai mirror url') | ||||
|     # operation options | ||||
| @@ -50,14 +50,6 @@ def cmd_parser(): | ||||
|     parser.add_option('--id', type='string', dest='id', action='store', help='doujinshi ids set, e.g. 1,2,3') | ||||
|     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('--artist', type='string', dest='artist', action='store', help='download doujinshi by artist') | ||||
|     parser.add_option('--character', type='string', dest='character', action='store', | ||||
|                       help='download doujinshi by character') | ||||
|     parser.add_option('--parody', type='string', dest='parody', action='store', help='download doujinshi by parody') | ||||
|     parser.add_option('--group', type='string', dest='group', action='store', help='download doujinshi by group') | ||||
|     parser.add_option('--language', type='string', dest='language', action='store', | ||||
|                       help='download doujinshi by language') | ||||
|     parser.add_option('--favorites', '-F', action='store_true', dest='favorites', | ||||
|                       help='list or download your favorites.') | ||||
|  | ||||
| @@ -95,14 +87,14 @@ def cmd_parser(): | ||||
|                       help='generate a main viewer contain all the doujin in the folder') | ||||
|     parser.add_option('--cbz', '-C', dest='is_cbz', action='store_true', | ||||
|                       help='generate Comic Book CBZ File') | ||||
|     parser.add_option('--comic-info', dest='write_comic_info', action='store_true', | ||||
|                       help='when generating Comic Book CBZ File, also write ComicInfo.xml') | ||||
|     parser.add_option('--rm-origin-dir', dest='rm_origin_dir', action='store_true', default=False, | ||||
|                       help='remove downloaded doujinshi dir when generated CBZ file.') | ||||
|  | ||||
|     # nhentai options | ||||
|     parser.add_option('--cookie', type='str', dest='cookie', action='store', | ||||
|                       help='set cookie of nhentai to bypass Google recaptcha') | ||||
|     parser.add_option('--language', type='str', dest='language', action='store', | ||||
|                       help='set default language to parse doujinshis') | ||||
|     parser.add_option('--save-download-history', dest='is_save_download_history', action='store_true', | ||||
|                       default=False, help='save downloaded doujinshis, whose will be skipped if you re-download them') | ||||
|     parser.add_option('--clean-download-history', action='store_true', default=False, dest='clean_download_history', | ||||
| @@ -123,8 +115,7 @@ def cmd_parser(): | ||||
|         exit(0) | ||||
|  | ||||
|     if args.main_viewer and not args.id and not args.keyword and \ | ||||
|             not args.tag and not args.artist and not args.character and \ | ||||
|             not args.parody and not args.group and not args.language and not args.favorites: | ||||
|             not args.tag and not args.favorites: | ||||
|         generate_main_html() | ||||
|         exit(0) | ||||
|  | ||||
| @@ -153,6 +144,25 @@ def cmd_parser(): | ||||
|         logger.info('Cookie saved.') | ||||
|         exit(0) | ||||
|  | ||||
|     if os.path.exists(constant.NHENTAI_LANGUAGE) and not args.language: | ||||
|         with open(constant.NHENTAI_LANGUAGE, 'r') as f: | ||||
|             constant.LANGUAGE = f.read() | ||||
|             args.language = f.read() | ||||
|  | ||||
|     if args.language: | ||||
|         try: | ||||
|             if not os.path.exists(constant.NHENTAI_HOME): | ||||
|                 os.mkdir(constant.NHENTAI_HOME) | ||||
|  | ||||
|             with open(constant.NHENTAI_LANGUAGE, 'w') as f: | ||||
|                 f.write(args.language) | ||||
|         except Exception as e: | ||||
|             logger.error('Cannot create NHENTAI_HOME: {}'.format(str(e))) | ||||
|             exit(1) | ||||
|  | ||||
|         logger.info('Default language now is {}.'.format(args.language)) | ||||
|         exit(0) | ||||
|  | ||||
|     if os.path.exists(constant.NHENTAI_PROXY): | ||||
|         with open(constant.NHENTAI_PROXY, 'r') as f: | ||||
|             link = f.read() | ||||
| @@ -192,14 +202,12 @@ def cmd_parser(): | ||||
|             args.id = set(int(i) for i in _ if i.isdigit()) | ||||
|  | ||||
|     if (args.is_download or args.is_show) and not args.id and not args.keyword and \ | ||||
|             not args.tag and not args.artist and not args.character and \ | ||||
|             not args.parody and not args.group and not args.language and not args.favorites: | ||||
|             not args.tag and not args.favorites: | ||||
|         logger.critical('Doujinshi id(s) are required for downloading') | ||||
|         parser.print_help() | ||||
|         exit(1) | ||||
|  | ||||
|     if not args.keyword and not args.id and not args.tag and not args.artist and \ | ||||
|             not args.character and not args.parody and not args.group and not args.language and not args.favorites: | ||||
|     if not args.keyword and not args.id and not  args.favorites: | ||||
|         parser.print_help() | ||||
|         exit(1) | ||||
|  | ||||
|   | ||||
| @@ -6,7 +6,7 @@ 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 | ||||
| from nhentai.parser import doujinshi_parser, search_parser, print_doujinshi, favorites_parser | ||||
| from nhentai.doujinshi import Doujinshi | ||||
| from nhentai.downloader import Downloader | ||||
| from nhentai.logger import logger | ||||
| @@ -21,14 +21,12 @@ def main(): | ||||
|  | ||||
|     from nhentai.constant import PROXY | ||||
|     # constant.PROXY will be changed after cmd_parser() | ||||
|     if PROXY != {}: | ||||
|     if PROXY: | ||||
|         logger.info('Using proxy: {0}'.format(PROXY)) | ||||
|  | ||||
|     # check your cookie | ||||
|     check_cookie() | ||||
|  | ||||
|     index = 0 | ||||
|     index_value = None | ||||
|     doujinshis = [] | ||||
|     doujinshi_ids = [] | ||||
|     doujinshi_list = [] | ||||
| @@ -39,38 +37,16 @@ def main(): | ||||
|  | ||||
|         doujinshis = favorites_parser(options.page_range) | ||||
|  | ||||
|     elif options.tag: | ||||
|         doujinshis = tag_parser(options.tag, sorting=options.sorting, max_page=options.max_page) | ||||
|  | ||||
|     elif options.artist: | ||||
|         index = 1 | ||||
|         index_value = options.artist | ||||
|  | ||||
|     elif options.character: | ||||
|         index = 2 | ||||
|         index_value = options.character | ||||
|  | ||||
|     elif options.parody: | ||||
|         index = 3 | ||||
|         index_value = options.parody | ||||
|  | ||||
|     elif options.group: | ||||
|         index = 4 | ||||
|         index_value = options.group | ||||
|  | ||||
|     elif options.language: | ||||
|         index = 5 | ||||
|         index_value = options.language | ||||
|  | ||||
|     elif options.keyword: | ||||
|         from nhentai.constant import LANGUAGE | ||||
|         if LANGUAGE: | ||||
|             logger.info('Using deafult language: {0}'.format(LANGUAGE)) | ||||
|             options.keyword += ', language:{}'.format(LANGUAGE) | ||||
|         doujinshis = search_parser(options.keyword, sorting=options.sorting, page=options.page) | ||||
|  | ||||
|     elif not doujinshi_ids: | ||||
|         doujinshi_ids = options.id | ||||
|  | ||||
|     if index: | ||||
|         doujinshis = tag_parser(index_value, max_page=options.max_page, index=index) | ||||
|  | ||||
|     print_doujinshi(doujinshis) | ||||
|     if options.is_download and doujinshis: | ||||
|         doujinshi_ids = [i['id'] for i in doujinshis] | ||||
| @@ -109,7 +85,7 @@ def main(): | ||||
|             if not options.is_nohtml and not options.is_cbz: | ||||
|                 generate_html(options.output_dir, doujinshi) | ||||
|             elif options.is_cbz: | ||||
|                 generate_cbz(options.output_dir, doujinshi, options.rm_origin_dir, options.write_comic_info) | ||||
|                 generate_cbz(options.output_dir, doujinshi, options.rm_origin_dir) | ||||
|  | ||||
|         if options.main_viewer: | ||||
|             generate_main_html(options.output_dir) | ||||
| @@ -125,6 +101,5 @@ def main(): | ||||
|  | ||||
| signal.signal(signal.SIGINT, signal_handler) | ||||
|  | ||||
|  | ||||
| if __name__ == '__main__': | ||||
|     main() | ||||
|   | ||||
| @@ -12,17 +12,10 @@ except ImportError: | ||||
| BASE_URL = os.getenv('NHENTAI', 'https://nhentai.net') | ||||
|  | ||||
| __api_suspended_DETAIL_URL = '%s/api/gallery' % BASE_URL | ||||
| __api_suspended_SEARCH_URL = '%s/api/galleries/search' % BASE_URL | ||||
|  | ||||
| DETAIL_URL = '%s/g' % BASE_URL | ||||
| SEARCH_URL = '%s/search/' % BASE_URL | ||||
| SEARCH_URL = '%s/api/galleries/search' % BASE_URL | ||||
|  | ||||
| TAG_URL = ['%s/tag' % BASE_URL, | ||||
|            '%s/artist' % BASE_URL, | ||||
|            '%s/character' % BASE_URL, | ||||
|            '%s/parody' % BASE_URL, | ||||
|            '%s/group' % BASE_URL, | ||||
|            '%s/language' % BASE_URL] | ||||
|  | ||||
| TAG_API_URL = '%s/api/galleries/tagged' % BASE_URL | ||||
| LOGIN_URL = '%s/login/' % BASE_URL | ||||
| @@ -35,8 +28,10 @@ IMAGE_URL = '%s://i.%s/galleries' % (u.scheme, u.hostname) | ||||
| NHENTAI_HOME = os.path.join(os.getenv('HOME', tempfile.gettempdir()), '.nhentai') | ||||
| NHENTAI_PROXY = os.path.join(NHENTAI_HOME, 'proxy') | ||||
| NHENTAI_COOKIE = os.path.join(NHENTAI_HOME, 'cookie') | ||||
| NHENTAI_LANGUAGE = os.path.join(NHENTAI_HOME, 'language') | ||||
| NHENTAI_HISTORY = os.path.join(NHENTAI_HOME, 'history.sqlite3') | ||||
|  | ||||
| PROXY = {} | ||||
|  | ||||
| COOKIE = '' | ||||
| LANGUAGE = '' | ||||
|   | ||||
| @@ -120,15 +120,15 @@ def page_range_parser(page_range, max_page_num): | ||||
|         else: | ||||
|             try: | ||||
|                 left = int(range_str[:idx]) | ||||
|                 right = int(range_str[idx+1:]) | ||||
|                 right = int(range_str[idx + 1:]) | ||||
|                 if right > max_page_num: | ||||
|                     right = max_page_num | ||||
|                 for page in range(left, right+1): | ||||
|                 for page in range(left, right + 1): | ||||
|                     pages.add(page) | ||||
|             except ValueError: | ||||
|                 logger.error('page range({0}) is not valid'.format(page_range)) | ||||
|      | ||||
|     return list(pages)     | ||||
|  | ||||
|     return list(pages) | ||||
|  | ||||
|  | ||||
| def doujinshi_parser(id_): | ||||
| @@ -143,7 +143,7 @@ def doujinshi_parser(id_): | ||||
|  | ||||
|     try: | ||||
|         response = request('get', url) | ||||
|         if response.status_code in (200, ): | ||||
|         if response.status_code in (200,): | ||||
|             response = response.content | ||||
|         else: | ||||
|             logger.debug('Slow down and retry ({}) ...'.format(id_)) | ||||
| @@ -202,7 +202,7 @@ def doujinshi_parser(id_): | ||||
|     return doujinshi | ||||
|  | ||||
|  | ||||
| def search_parser(keyword, sorting='date', page=1): | ||||
| def old_search_parser(keyword, sorting='date', page=1): | ||||
|     logger.debug('Searching doujinshis of keyword {0}'.format(keyword)) | ||||
|     response = request('get', url=constant.SEARCH_URL, params={'q': keyword, 'page': page, 'sort': sorting}).content | ||||
|  | ||||
| @@ -222,50 +222,15 @@ def print_doujinshi(doujinshi_list): | ||||
|                 tabulate(tabular_data=doujinshi_list, headers=headers, tablefmt='rst')) | ||||
|  | ||||
|  | ||||
| def tag_parser(tag_name, sorting='date', max_page=1, index=0): | ||||
|     result = [] | ||||
|     tag_name = tag_name.lower() | ||||
|     if ',' in tag_name: | ||||
|         tag_name = [i.strip().replace(' ', '-') for i in tag_name.split(',')] | ||||
|     else: | ||||
|         tag_name = tag_name.strip().replace(' ', '-') | ||||
|     if sorting == 'date': | ||||
|         sorting = '' | ||||
|  | ||||
|     for p in range(1, max_page + 1): | ||||
|         if sys.version_info >= (3, 0, 0): | ||||
|             unicode_ = str | ||||
|         else: | ||||
|             unicode_ = unicode | ||||
|  | ||||
|         if isinstance(tag_name, (str, unicode_)): | ||||
|             logger.debug('Fetching page {0} for doujinshi with tag \'{1}\''.format(p, tag_name)) | ||||
|             response = request('get', url='%s/%s/%s?page=%d' % (constant.TAG_URL[index], tag_name, sorting, p)).content | ||||
|             result += _get_title_and_id(response) | ||||
|         else: | ||||
|             for i in tag_name: | ||||
|                 logger.debug('Fetching page {0} for doujinshi with tag \'{1}\''.format(p, i)) | ||||
|                 response = request('get', | ||||
|                                    url='%s/%s/%s?page=%d' % (constant.TAG_URL[index], i, sorting, p)).content | ||||
|                 result += _get_title_and_id(response) | ||||
|  | ||||
|         if not result: | ||||
|             logger.error('Cannot find doujinshi id of tag \'{0}\''.format(tag_name)) | ||||
|             return | ||||
|  | ||||
|     if not result: | ||||
|         logger.warn('No results for tag \'{}\''.format(tag_name)) | ||||
|  | ||||
|     return result | ||||
|  | ||||
|  | ||||
| def __api_suspended_search_parser(keyword, sorting, page): | ||||
| def search_parser(keyword, sorting, page): | ||||
|     logger.debug('Searching doujinshis using keywords {0}'.format(keyword)) | ||||
|     keyword = '+'.join([i.strip().replace(' ', '-').lower() for i in keyword.split(',')]) | ||||
|     result = [] | ||||
|     i = 0 | ||||
|     while i < 5: | ||||
|         try: | ||||
|             response = request('get', url=constant.SEARCH_URL, params={'query': keyword, 'page': page, 'sort': sorting}).json() | ||||
|             url = request('get', url=constant.SEARCH_URL, params={'query': keyword, 'page': page, 'sort': sorting}).url | ||||
|             response = request('get', url.replace('%2B', '+')).json() | ||||
|         except Exception as e: | ||||
|             i += 1 | ||||
|             if not i < 5: | ||||
| @@ -289,29 +254,6 @@ def __api_suspended_search_parser(keyword, sorting, page): | ||||
|     return result | ||||
|  | ||||
|  | ||||
| def __api_suspended_tag_parser(tag_id, sorting, max_page=1): | ||||
|     logger.info('Searching for doujinshi with tag id {0}'.format(tag_id)) | ||||
|     result = [] | ||||
|     response = request('get', url=constant.TAG_API_URL, params={'sort': sorting, 'tag_id': tag_id}).json() | ||||
|     page = max_page if max_page <= response['num_pages'] else int(response['num_pages']) | ||||
|  | ||||
|     for i in range(1, page + 1): | ||||
|         logger.info('Getting page {} ...'.format(i)) | ||||
|  | ||||
|         if page != 1: | ||||
|             response = request('get', url=constant.TAG_API_URL, | ||||
|                                params={'sort': sorting, 'tag_id': tag_id}).json() | ||||
|     for row in response['result']: | ||||
|         title = row['title']['english'] | ||||
|         title = title[:85] + '..' if len(title) > 85 else title | ||||
|         result.append({'id': row['id'], 'title': title}) | ||||
|  | ||||
|     if not result: | ||||
|         logger.warn('No results for tag id {}'.format(tag_id)) | ||||
|  | ||||
|     return result | ||||
|  | ||||
|  | ||||
| def __api_suspended_doujinshi_parser(id_): | ||||
|     if not isinstance(id_, (int,)) and (isinstance(id_, (str,)) and not id_.isdigit()): | ||||
|         raise Exception('Doujinshi id({0}) is not valid'.format(id_)) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user