Add search function

This commit is contained in:
Thomas Wade 2020-04-25 03:06:13 +09:30
parent 6a6334b912
commit 03905756ca
2 changed files with 122 additions and 1 deletions

View File

@ -1,4 +1,5 @@
from datetime import datetime
from enum import Enum
from typing import List
import requests
@ -444,6 +445,64 @@ class User:
return self.username
class OrderByEnum(Enum):
relevancy = 'relevancy'
date = 'date'
popularity = 'popularity'
class OrderEnum(Enum):
ascending = 'asc'
descending = 'desc'
class RangeEnum(Enum):
day = 'day'
three_days = '3days'
week = 'week'
month = 'month'
all_time = 'all'
class MatchModeEnum(Enum):
all = 'all'
any = 'any'
extended = 'extended'
class SearchOpts:
"""
A container for FurAffinity search options.
"""
def __init__(self, order_by: OrderByEnum = OrderByEnum.relevancy,
order_direction: OrderEnum = OrderEnum.descending,
range: RangeEnum = RangeEnum.all_time,
match_mode: MatchModeEnum = MatchModeEnum.extended,
rating_general: bool = True,
rating_mature: bool = True,
rating_adult: bool = True,
type_art: bool = True,
type_music: bool = True,
type_flash: bool = True,
type_story: bool = True,
type_photo: bool = True,
type_poetry: bool = True):
self.order_by: OrderByEnum = order_by
self.order_direction: OrderEnum = order_direction
self.range: RangeEnum = range
self.match_mode: MatchModeEnum = match_mode
self.rating_general: bool = rating_general
self.rating_mature: bool = rating_mature
self.rating_adult: bool = rating_adult
self.type_art: bool = type_art
self.type_music: bool = type_music
self.type_flash: bool = type_flash
self.type_story: bool = type_story
self.type_photo: bool = type_photo
self.type_poetry: bool = type_poetry
class FAAPI:
"""
A basic FurAffinity API instance.
@ -567,6 +626,68 @@ class FAAPI:
submission._api = self
return submission
def search(self, search: str, results: int = 48, opts: SearchOpts = SearchOpts()) -> List[Submission]:
"""
Searches FurAffinity with the given string.
Results are
:param search: Search term
:param results: Number of results to return
:param opts: Search options
:return: List containing results
"""
url = FA_BASE_URL + '/search/'
form_data = {
'page': 1,
'q': search,
'do_search': 'Search',
'order-by': opts.order_by,
'order-direction': opts.order_direction,
'range': opts.range,
'mode': opts.match_mode
}
# Set optional keys since they're judged on presence, not value
if opts.rating_general: form_data['rating-general'] = 'on'
if opts.rating_mature: form_data['rating-mature'] = 'on'
if opts.rating_adult: form_data['rating-adult'] = 'on'
if opts.type_art: form_data['type-art'] = 'on'
if opts.type_music: form_data['type-music'] = 'on'
if opts.type_flash: form_data['type-flash'] = 'on'
if opts.type_story: form_data['type-story'] = 'on'
if opts.type_photo: form_data['type-photo'] = 'on'
if opts.type_poetry: form_data['type-poetry'] = 'on'
submissions = []
while len(submissions) < results:
# Get our search results
res = self._req.post(url, data=form_data)
if res.status_code >= 400:
raise Exception('Got status code {} when trying to get URL {}'.format(res.status_code, url))
soup = BeautifulSoup(res.content, 'lxml')
# Get all the submissions on this page
items = soup.select('.gallery figure')
for item in items:
sub = self.get_submission(int(item.get('id')[4:])) # IDs look like 'sid-35908275', so we just skip the 'sid-'
# Try cache the preview URL early
try:
sub._preview_url = 'https:' + item.select('img')[0].get('src')
sub._has_preview = True
except IndexError:
sub._has_preview = False
submissions.append(sub)
if not soup.select('input[name=next_page]:not(.hidden)'):
# No further pages, stop searching
break
# Increment our page number
form_data['page'] = form_data['page'] + 1
return submissions[:results]
def __getstate__(self):
# Get a copy of the object state without the requests session
state = self.__dict__.copy()

View File

@ -2,7 +2,7 @@ from setuptools import setup, find_packages
setup(
name='FAAPI',
version='0.5.4',
version='0.6.0',
packages=find_packages(),
url='https://tem.party/gitea/tom/FAAPI',
license='WTFPL',