Add support for loading structures directly from python json objects (#1092)
This commit is contained in:
parent
3837b642b0
commit
fa19b95107
@ -77,6 +77,10 @@ Loading and Saving
|
|||||||
:class:`Post`, :class:`StoryItem`, :class:`Profile`, :class:`Hashtag` and
|
:class:`Post`, :class:`StoryItem`, :class:`Profile`, :class:`Hashtag` and
|
||||||
:class:`FrozenNodeIterator` can be saved and loaded to/from JSON files.
|
:class:`FrozenNodeIterator` can be saved and loaded to/from JSON files.
|
||||||
|
|
||||||
|
.. autofunction:: load_structure
|
||||||
|
|
||||||
.. autofunction:: load_structure_from_file
|
.. autofunction:: load_structure_from_file
|
||||||
|
|
||||||
|
.. autofunction:: get_json_structure
|
||||||
|
|
||||||
.. autofunction:: save_structure_to_file
|
.. autofunction:: save_structure_to_file
|
||||||
|
@ -17,4 +17,5 @@ from .instaloader import Instaloader
|
|||||||
from .instaloadercontext import InstaloaderContext, RateController
|
from .instaloadercontext import InstaloaderContext, RateController
|
||||||
from .nodeiterator import NodeIterator, FrozenNodeIterator, resumable_iteration
|
from .nodeiterator import NodeIterator, FrozenNodeIterator, resumable_iteration
|
||||||
from .structures import (Hashtag, Highlight, Post, PostSidecarNode, PostComment, PostCommentAnswer, PostLocation,
|
from .structures import (Hashtag, Highlight, Post, PostSidecarNode, PostComment, PostCommentAnswer, PostLocation,
|
||||||
Profile, Story, StoryItem, TopSearchResults, load_structure_from_file, save_structure_to_file)
|
Profile, Story, StoryItem, TopSearchResults, load_structure_from_file, save_structure_to_file,
|
||||||
|
load_structure, get_json_structure)
|
||||||
|
@ -1540,6 +1540,20 @@ class TopSearchResults:
|
|||||||
JsonExportable = Union[Post, Profile, StoryItem, Hashtag, FrozenNodeIterator]
|
JsonExportable = Union[Post, Profile, StoryItem, Hashtag, FrozenNodeIterator]
|
||||||
|
|
||||||
|
|
||||||
|
def get_json_structure(structure: JsonExportable) -> dict:
|
||||||
|
"""Returns Instaloader JSON structure for a :class:`Post`, :class:`Profile`, :class:`StoryItem`, :class:`Hashtag`
|
||||||
|
or :class:`FrozenNodeIterator` so that it can be loaded by :func:`load_structure`.
|
||||||
|
|
||||||
|
:param structure: :class:`Post`, :class:`Profile`, :class:`StoryItem` or :class:`Hashtag`
|
||||||
|
|
||||||
|
.. versionadded:: 4.8
|
||||||
|
"""
|
||||||
|
return {
|
||||||
|
'node': structure._asdict(),
|
||||||
|
'instaloader': {'version': __version__, 'node_type': structure.__class__.__name__}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def save_structure_to_file(structure: JsonExportable, filename: str) -> None:
|
def save_structure_to_file(structure: JsonExportable, filename: str) -> None:
|
||||||
"""Saves a :class:`Post`, :class:`Profile`, :class:`StoryItem`, :class:`Hashtag` or :class:`FrozenNodeIterator` to a
|
"""Saves a :class:`Post`, :class:`Profile`, :class:`StoryItem`, :class:`Hashtag` or :class:`FrozenNodeIterator` to a
|
||||||
'.json' or '.json.xz' file such that it can later be loaded by :func:`load_structure_from_file`.
|
'.json' or '.json.xz' file such that it can later be loaded by :func:`load_structure_from_file`.
|
||||||
@ -1550,8 +1564,7 @@ def save_structure_to_file(structure: JsonExportable, filename: str) -> None:
|
|||||||
:param structure: :class:`Post`, :class:`Profile`, :class:`StoryItem` or :class:`Hashtag`
|
:param structure: :class:`Post`, :class:`Profile`, :class:`StoryItem` or :class:`Hashtag`
|
||||||
:param filename: Filename, ends in '.json' or '.json.xz'
|
:param filename: Filename, ends in '.json' or '.json.xz'
|
||||||
"""
|
"""
|
||||||
json_structure = {'node': structure._asdict(),
|
json_structure = get_json_structure(structure)
|
||||||
'instaloader': {'version': __version__, 'node_type': structure.__class__.__name__}}
|
|
||||||
compress = filename.endswith('.xz')
|
compress = filename.endswith('.xz')
|
||||||
if compress:
|
if compress:
|
||||||
with lzma.open(filename, 'wt', check=lzma.CHECK_NONE) as fp:
|
with lzma.open(filename, 'wt', check=lzma.CHECK_NONE) as fp:
|
||||||
@ -1561,6 +1574,34 @@ def save_structure_to_file(structure: JsonExportable, filename: str) -> None:
|
|||||||
json.dump(json_structure, fp=fp, indent=4, sort_keys=True)
|
json.dump(json_structure, fp=fp, indent=4, sort_keys=True)
|
||||||
|
|
||||||
|
|
||||||
|
def load_structure(context: InstaloaderContext, json_structure: dict) -> JsonExportable:
|
||||||
|
"""Loads a :class:`Post`, :class:`Profile`, :class:`StoryItem`, :class:`Hashtag` or :class:`FrozenNodeIterator` from
|
||||||
|
a json structure.
|
||||||
|
|
||||||
|
:param context: :attr:`Instaloader.context` linked to the new object, used for additional queries if neccessary.
|
||||||
|
:param json_structure: Instaloader JSON structure
|
||||||
|
|
||||||
|
.. versionadded:: 4.8
|
||||||
|
"""
|
||||||
|
if 'node' in json_structure and 'instaloader' in json_structure and \
|
||||||
|
'node_type' in json_structure['instaloader']:
|
||||||
|
node_type = json_structure['instaloader']['node_type']
|
||||||
|
if node_type == "Post":
|
||||||
|
return Post(context, json_structure['node'])
|
||||||
|
elif node_type == "Profile":
|
||||||
|
return Profile(context, json_structure['node'])
|
||||||
|
elif node_type == "StoryItem":
|
||||||
|
return StoryItem(context, json_structure['node'])
|
||||||
|
elif node_type == "Hashtag":
|
||||||
|
return Hashtag(context, json_structure['node'])
|
||||||
|
elif node_type == "FrozenNodeIterator":
|
||||||
|
return FrozenNodeIterator(**json_structure['node'])
|
||||||
|
elif 'shortcode' in json_structure:
|
||||||
|
# Post JSON created with Instaloader v3
|
||||||
|
return Post.from_shortcode(context, json_structure['shortcode'])
|
||||||
|
raise InvalidArgumentException("Passed json structure is not an Instaloader JSON")
|
||||||
|
|
||||||
|
|
||||||
def load_structure_from_file(context: InstaloaderContext, filename: str) -> JsonExportable:
|
def load_structure_from_file(context: InstaloaderContext, filename: str) -> JsonExportable:
|
||||||
"""Loads a :class:`Post`, :class:`Profile`, :class:`StoryItem`, :class:`Hashtag` or :class:`FrozenNodeIterator` from
|
"""Loads a :class:`Post`, :class:`Profile`, :class:`StoryItem`, :class:`Hashtag` or :class:`FrozenNodeIterator` from
|
||||||
a '.json' or '.json.xz' file that has been saved by :func:`save_structure_to_file`.
|
a '.json' or '.json.xz' file that has been saved by :func:`save_structure_to_file`.
|
||||||
@ -1575,23 +1616,4 @@ def load_structure_from_file(context: InstaloaderContext, filename: str) -> Json
|
|||||||
fp = open(filename, 'rt')
|
fp = open(filename, 'rt')
|
||||||
json_structure = json.load(fp)
|
json_structure = json.load(fp)
|
||||||
fp.close()
|
fp.close()
|
||||||
if 'node' in json_structure and 'instaloader' in json_structure and \
|
return load_structure(context, json_structure)
|
||||||
'node_type' in json_structure['instaloader']:
|
|
||||||
node_type = json_structure['instaloader']['node_type']
|
|
||||||
if node_type == "Post":
|
|
||||||
return Post(context, json_structure['node'])
|
|
||||||
elif node_type == "Profile":
|
|
||||||
return Profile(context, json_structure['node'])
|
|
||||||
elif node_type == "StoryItem":
|
|
||||||
return StoryItem(context, json_structure['node'])
|
|
||||||
elif node_type == "Hashtag":
|
|
||||||
return Hashtag(context, json_structure['node'])
|
|
||||||
elif node_type == "FrozenNodeIterator":
|
|
||||||
return FrozenNodeIterator(**json_structure['node'])
|
|
||||||
else:
|
|
||||||
raise InvalidArgumentException("{}: Not an Instaloader JSON.".format(filename))
|
|
||||||
elif 'shortcode' in json_structure:
|
|
||||||
# Post JSON created with Instaloader v3
|
|
||||||
return Post.from_shortcode(context, json_structure['shortcode'])
|
|
||||||
else:
|
|
||||||
raise InvalidArgumentException("{}: Not an Instaloader JSON.".format(filename))
|
|
||||||
|
Loading…
Reference in New Issue
Block a user