diff --git a/snscrape/base.py b/snscrape/base.py index 6860845..dcf4181 100644 --- a/snscrape/base.py +++ b/snscrape/base.py @@ -217,3 +217,13 @@ class Scraper: @classmethod def _construct(cls, argparseArgs, *args, **kwargs): return cls(*args, **kwargs, retries = argparseArgs.retries) + + +def nonempty_string(name): + def f(s): + s = s.strip() + if s: + return s + raise ValueError('must not be an empty string') + f.__name__ = name + return f diff --git a/snscrape/modules/facebook.py b/snscrape/modules/facebook.py index db205f5..cefe14c 100644 --- a/snscrape/modules/facebook.py +++ b/snscrape/modules/facebook.py @@ -203,7 +203,7 @@ class FacebookUserAndCommunityScraper(FacebookCommonScraper): @classmethod def setup_parser(cls, subparser): - subparser.add_argument('username', help = 'A Facebook username or user ID') + subparser.add_argument('username', type = snscrape.base.nonempty_string('username'), help = 'A Facebook username or user ID') @classmethod def from_args(cls, args): @@ -354,7 +354,7 @@ class FacebookGroupScraper(FacebookCommonScraper): @classmethod def setup_parser(cls, subparser): - subparser.add_argument('group', help = 'A group name or ID') + subparser.add_argument('group', type = snscrape.base.nonempty_string('group'), help = 'A group name or ID') @classmethod def from_args(cls, args): diff --git a/snscrape/modules/instagram.py b/snscrape/modules/instagram.py index cb4f5d3..442b1f2 100644 --- a/snscrape/modules/instagram.py +++ b/snscrape/modules/instagram.py @@ -174,7 +174,7 @@ class InstagramUserScraper(InstagramCommonScraper): @classmethod def setup_parser(cls, subparser): - subparser.add_argument('username', help = 'An Instagram username (no leading @)') + subparser.add_argument('username', type = snscrape.base.nonempty_string('username'), help = 'An Instagram username (no leading @)') @classmethod def from_args(cls, args): @@ -219,7 +219,7 @@ class InstagramHashtagScraper(InstagramCommonScraper): @classmethod def setup_parser(cls, subparser): - subparser.add_argument('hashtag', help = 'An Instagram hashtag (no leading #)') + subparser.add_argument('hashtag', type = snscrape.base.nonempty_string('hashtag'), help = 'An Instagram hashtag (no leading #)') @classmethod def from_args(cls, args): diff --git a/snscrape/modules/reddit.py b/snscrape/modules/reddit.py index bc4c721..d8acb38 100644 --- a/snscrape/modules/reddit.py +++ b/snscrape/modules/reddit.py @@ -218,7 +218,7 @@ def _make_scraper(name_, validationFunc, apiField): @classmethod def setup_parser(cls, subparser): super()._setup_parser_opts(subparser) - subparser.add_argument(name_) + subparser.add_argument(name_, type = snscrape.base.nonempty_string(name_)) @classmethod def from_args(cls, args): diff --git a/snscrape/modules/telegram.py b/snscrape/modules/telegram.py index 8b64ca3..04a229c 100644 --- a/snscrape/modules/telegram.py +++ b/snscrape/modules/telegram.py @@ -193,7 +193,7 @@ class TelegramChannelScraper(snscrape.base.Scraper): @classmethod def setup_parser(cls, subparser): - subparser.add_argument('channel', help = 'A channel name') + subparser.add_argument('channel', type = snscrape.base.nonempty_string('channel'), help = 'A channel name') @classmethod def from_args(cls, args): diff --git a/snscrape/modules/twitter.py b/snscrape/modules/twitter.py index 3f08efe..1e96a36 100644 --- a/snscrape/modules/twitter.py +++ b/snscrape/modules/twitter.py @@ -495,6 +495,8 @@ class TwitterSearchScraper(TwitterAPIScraper): name = 'twitter-search' def __init__(self, query, cursor = None, top = False, **kwargs): + if not query.strip(): + raise ValueError('empty query') super().__init__(baseUrl = 'https://twitter.com/search?' + urllib.parse.urlencode({'f': 'live', 'lang': 'en', 'q': query, 'src': 'spelling_expansion_revert_click'}), **kwargs) self._query = query # Note: may get replaced by subclasses when using user ID resolution self._cursor = cursor @@ -511,6 +513,8 @@ class TwitterSearchScraper(TwitterAPIScraper): return True, None def get_items(self): + if not self._query.strip(): + raise ValueError('empty query') paginationParams = { 'include_profile_interstitial_type': '1', 'include_blocking': '1', @@ -556,7 +560,7 @@ class TwitterSearchScraper(TwitterAPIScraper): def setup_parser(cls, subparser): subparser.add_argument('--cursor', metavar = 'CURSOR') subparser.add_argument('--top', action = 'store_true', default = False, help = 'Enable fetching top tweets instead of live/chronological') - subparser.add_argument('query', help = 'A Twitter search string') + subparser.add_argument('query', type = snscrape.base.nonempty_string('query'), help = 'A Twitter search string') @classmethod def from_args(cls, args): @@ -695,7 +699,7 @@ class TwitterHashtagScraper(TwitterSearchScraper): @classmethod def setup_parser(cls, subparser): - subparser.add_argument('hashtag', help = 'A Twitter hashtag (without #)') + subparser.add_argument('hashtag', type = snscrape.base.nonempty_string('hashtag'), help = 'A Twitter hashtag (without #)') @classmethod def from_args(cls, args): @@ -795,7 +799,7 @@ class TwitterListPostsScraper(TwitterSearchScraper): @classmethod def setup_parser(cls, subparser): - subparser.add_argument('list', help = 'A Twitter list ID or a string of the form "username/listname" (replace spaces with dashes)') + subparser.add_argument('list', type = snscrape.base.nonempty_string('list'), help = 'A Twitter list ID or a string of the form "username/listname" (replace spaces with dashes)') @classmethod def from_args(cls, args): diff --git a/snscrape/modules/vkontakte.py b/snscrape/modules/vkontakte.py index 1703baf..aef0610 100644 --- a/snscrape/modules/vkontakte.py +++ b/snscrape/modules/vkontakte.py @@ -366,7 +366,7 @@ class VKontakteUserScraper(snscrape.base.Scraper): @classmethod def setup_parser(cls, subparser): - subparser.add_argument('username', help = 'A VK username') + subparser.add_argument('username', type = snscrape.base.nonempty_string('username'), help = 'A VK username') @classmethod def from_args(cls, args): diff --git a/snscrape/modules/weibo.py b/snscrape/modules/weibo.py index d972461..395fc1f 100644 --- a/snscrape/modules/weibo.py +++ b/snscrape/modules/weibo.py @@ -139,7 +139,7 @@ class WeiboUserScraper(snscrape.base.Scraper): @classmethod def setup_parser(cls, subparser): - subparser.add_argument('user', help = 'A user name or ID') + subparser.add_argument('user', type = snscrape.base.nonempty_string('user'), help = 'A user name or ID') @classmethod def from_args(cls, args):