-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
gavinzbq
committed
Jun 22, 2017
1 parent
9a823d9
commit 14f31a2
Showing
8 changed files
with
263 additions
and
87 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,29 +1,20 @@ | ||
# Config file for automatic testing at travis-ci.org | ||
# This file will be regenerated if you run travis_pypi_setup.py | ||
|
||
language: python | ||
python: | ||
- 3.5 | ||
- 3.4 | ||
- 3.3 | ||
- 2.7 | ||
- 2.6 | ||
|
||
# command to install dependencies, e.g. pip install -r requirements.txt --use-mirrors | ||
install: pip install -U tox-travis | ||
|
||
# command to run tests, e.g. python setup.py test | ||
script: tox | ||
|
||
# After you create the Github repo and add it to Travis, run the | ||
# travis_pypi_setup.py script to finish PyPI deployment setup | ||
# This file was autogenerated and will overwrite each time you run travis_pypi_setup.py | ||
deploy: | ||
provider: pypi | ||
true: | ||
python: 2.7 | ||
repo: gavinzbq/synonym | ||
tags: true | ||
distributions: sdist bdist_wheel | ||
user: gavinzbq | ||
password: | ||
secure: PLEASE_REPLACE_ME | ||
on: | ||
tags: true | ||
repo: gavinzbq/synonym | ||
python: 2.7 | ||
secure: cK1HjxAb3d8mxQEuJBZ16puwieKBFlurC43L+3/9pXGoM9RHxW1konEhroxKHaxa3K4ul3lvOr0o9X/1/nlznkCo9tlh3z2lnusvK0Adj1Wzg+DfkfWzm7fBnlPuTY5o1ypMbImWSOfpP9Ia1ALM1IphMjaIlSQGXMTN/p+tn8QEclQaEH/j0LfNTwiyhH+bP41DFXljaQO1lRHdwzkuUlVjBRQ7lL4tA0U0fDEqPQVOhfGY2hABP+dzq37YRXVTlUyV1ntYQtIB0HrFTeOwRQDaZCc3UqbEx6vscBP2s5XzgbyO+yn7ViO+u5az0BRfZjTtQ/qD1ziJww5Wvh3L630ya5YrYcIrdaBQ1aur+dBfAAGHYAvHEvK3zpdU7nV+9TQReJmEyfvGlTmDSEESmst/v5oHAlGKdRE15GtsfQe4JygpsgQIqN/JG+f+Bsa6n2m7zefzyXmZQLEbTu4uhoAsc/Ba2g0fznB+X516ta1gj78Rutb+adWf75rSvIaqgCTbH29vOWlcx1mKZfVk3Of99qIQBzclOTgsIuy9q9bEnErkI7oqt0H0flj+NuQf17G1z4aZ9VuuEzA8geRkblqHgWS7qnTRs5MeBaS28w3T1qdUlbd/KLiZq0OcV/qyO6gm0b7sQhUOwSeDUqeh3RuQlb8MCg5oazJ6DzHAoQw= | ||
provider: pypi | ||
user: gavinzbq | ||
install: pip install -U tox-travis | ||
language: python | ||
python: | ||
- 3.5 | ||
- 3.4 | ||
- 3.3 | ||
- 2.7 | ||
- 2.6 | ||
script: tox |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,4 +8,6 @@ coverage==4.1 | |
Sphinx==1.4.8 | ||
cryptography==1.7 | ||
PyYAML==3.11 | ||
|
||
pyquery==1.2.17 | ||
requests==2.18.1 | ||
crayons==0.1.2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,235 @@ | ||
# -*- coding: utf-8 -*- | ||
#!/usr/bin/env python | ||
|
||
"""Main module.""" | ||
######################################################## | ||
# | ||
# synonym - instant synonym answers via command line | ||
# written by Shanyun Gao (shanyungau@gmail.com) | ||
# inspired by howdoi (http://github.com/gleitz/howdoi ) | ||
# | ||
######################################################## | ||
|
||
|
||
import argparse | ||
import random | ||
import os | ||
import requests | ||
import sys | ||
import crayons | ||
|
||
from pyquery import PyQuery as pq | ||
from requests.exceptions import ConnectionError | ||
from requests.exceptions import SSLError | ||
|
||
# Handle imports from Python 2 and 3 | ||
if sys.version < '3': | ||
import codecs | ||
from urllib import quote as url_quote | ||
from urllib import getproxies | ||
|
||
# Handle Unicode | ||
def u(x): | ||
return codecs.unicode_escape_decode(x)[0] | ||
else: | ||
from urllib.request import getproxies | ||
from urllib.parse import quote as url_quote | ||
|
||
def u(x): | ||
return x | ||
|
||
if os.getenv('SYNONYM_DISABLE_SSL'): # Set http instead of https | ||
SEARCH_URL = 'http://www.thesaurus.com/browse/{0}?s=t' | ||
VERIFY_SSL_CERTIFICATE = False | ||
else: | ||
SEARCH_URL = 'https://www.thesaurus.com/browse/{0}?s=t' | ||
VERIFY_SSL_CERTIFICATE = True | ||
|
||
URL = 'www.thesaurus.com' | ||
|
||
USER_AGENTS = ('Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:11.0) Gecko/20100101 Firefox/11.0', | ||
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100 101 Firefox/22.0', | ||
'Mozilla/5.0 (Windows NT 6.1; rv:11.0) Gecko/20100101 Firefox/11.0', | ||
('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/536.5 (KHTML, like Gecko) ' | ||
'Chrome/19.0.1084.46 Safari/536.5'), | ||
('Mozilla/5.0 (Windows; Windows NT 6.1) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.46' | ||
'Safari/536.5'), ) | ||
|
||
|
||
def get_proxies(): | ||
proxies = getproxies() | ||
filtered_proxies = {} | ||
for key, value in proxies.items(): | ||
if key.startswith('http'): | ||
if not value.startswith('http'): | ||
filtered_proxies[key] = 'http://%s' % value | ||
else: | ||
filtered_proxies[key] = value | ||
return filtered_proxies | ||
|
||
|
||
def _get_result(url): | ||
try: | ||
return requests.get(url, headers={'User-Agent': random.choice(USER_AGENTS)}, proxies=get_proxies(), | ||
verify=VERIFY_SSL_CERTIFICATE).text | ||
except requests.exceptions.SSLError as e: | ||
print('[ERROR] Encountered an SSL Error. Try using HTTP instead of ' | ||
'HTTPS by setting the environment variable "SYNONYM_DISABLE_SSL".\n') | ||
raise e | ||
|
||
|
||
def _get_link(query): | ||
return SEARCH_URL.format(query) | ||
|
||
|
||
def _get_answer(args, link): | ||
page = _get_result(link) | ||
html = pq(page) | ||
all_answers = html('.filters') | ||
|
||
if len(all_answers) == 0: | ||
syn_answers = crayons.red( | ||
'\nCannot find synonym for "{}".\n'.format(args['query'][0]) | ||
) | ||
return syn_answers | ||
|
||
if len(all_answers) == 1: | ||
answer = all_answers.eq(0) | ||
prop = answer('.synonym-description').find('.txt').text() | ||
defn = answer('.synonym-description').find('.ttl').text() | ||
if not (prop or defn): | ||
guess = answer('.heading-row').find('a') | ||
guess_word = guess.text() | ||
syn_answers = crayons.red( | ||
'\nCannot find synonym for "{}". Try "{}"?\n'.format(args['query'][0], guess_word) | ||
) | ||
return syn_answers | ||
|
||
import ast | ||
syn_answers = [] | ||
index = 0 | ||
for answer in all_answers.items(): | ||
prop = answer('.synonym-description').find('.txt').text() | ||
defn = answer('.synonym-description').find('.ttl').text() | ||
|
||
syn_answers.append((prop, defn, {})) | ||
syn_list = answer('a') | ||
for syn in syn_list.items(): | ||
relevancy_str = syn.attr['data-category'] | ||
relevancy_dict = ast.literal_eval(relevancy_str) | ||
relevancy_lv = relevancy_dict['name'] | ||
|
||
if relevancy_lv not in syn_answers[index][2]: | ||
syn_answers[index][2][relevancy_lv] = [syn('.text').text()] | ||
else: | ||
syn_answers[index][2][relevancy_lv].append(syn('.text').text()) | ||
index += 1 | ||
|
||
return syn_answers | ||
|
||
|
||
def _filter_answer(args): | ||
answer_url = _get_link(args['query'][0]) | ||
all_answers = _get_answer(args, answer_url) | ||
|
||
if type(all_answers) in [str, crayons.ColoredString]: | ||
return all_answers | ||
|
||
if not args['property']: | ||
return all_answers | ||
|
||
filter_answer = [] | ||
if args['property'] == 'n': | ||
for answer in all_answers: | ||
if answer[0] == 'noun': | ||
filter_answer.append(answer) | ||
if args['property'] == 'v': | ||
for answer in all_answers: | ||
if answer[0] == 'verb': | ||
filter_answer.append(answer) | ||
if args['property'] == 'adj': | ||
for answer in all_answers: | ||
if answer[0] == 'adj': | ||
filter_answer.append(answer) | ||
if args['property'] == 'adv': | ||
for answer in all_answers: | ||
if answer[0] == 'adv': | ||
filter_answer.append(answer) | ||
|
||
if not filter_answer: | ||
return crayons.magenta( | ||
'\nIt seems, "{}" has no such property.\n'.format(args['query'][0]) | ||
) | ||
|
||
return filter_answer | ||
|
||
|
||
def _display_answer(args): | ||
answer_url = _get_link(args['query'][0]) | ||
answers = _filter_answer(args) | ||
|
||
if type(answers) in [str, crayons.ColoredString]: | ||
return answers | ||
|
||
texts = '' | ||
texts += crayons.green( | ||
'--- Synonyms for "{}" ---\n\n'.format(args['query'][0]) | ||
) | ||
for answer in answers: | ||
texts += crayons.red('=== {}. {} ===\n\n'.format(answer[0], answer[1])) | ||
if len(answer[2]) == 0: | ||
texts += crayons.magenta( | ||
'Whoops-a-daisy, no synonyms for {} found.'.format(args['query'][0]) | ||
) | ||
elif len(answer[2]) == 1: | ||
(k, v), = answer[2].items() | ||
texts += ', '.join(v) | ||
texts += '\n\n' | ||
else: | ||
if 'relevant-3' in answer[2]: | ||
texts += crayons.green('Most relevant synonyms:\n') | ||
texts += ', '.join(answer[2]['relevant-3']) | ||
texts += crayons.green('\n\nLess relevant synonyms:\n') | ||
if 'relevant-2' in answer[2]: | ||
texts += ', '.join(answer[2]['relevant-2']) | ||
else: | ||
texts += ', '.join(answer[2]['relevant-1']) | ||
texts += '\n\n' | ||
else: | ||
texts += ', '.join(answer[2]['relevant-2']) | ||
texts += '\n\n' | ||
|
||
texts += crayons.green('---\nAnswer from {}'.format(answer_url)) | ||
return texts | ||
|
||
|
||
def get_parser(): | ||
parser = argparse.ArgumentParser(description='instant synonym answers via command line') | ||
parser.add_argument('query', metavar='Word of Interest', type=str, nargs=1, help='The word of interest') | ||
parser.add_argument('-p', '--property', help='The property of interest (type n / v / adj / adv)', | ||
type=str, choices=['n', 'v', 'adj', 'adv']) | ||
return parser | ||
|
||
|
||
def synonym(args): | ||
try: | ||
return _display_answer(args) | ||
except (ConnectionError, SSLError): | ||
return 'Failed to establish network connection.\n' | ||
|
||
|
||
def command_line_runner(): | ||
parser = get_parser() | ||
args = vars(parser.parse_args()) | ||
|
||
if not args['query']: | ||
parser.print_help | ||
return | ||
|
||
if sys.version < '3': | ||
print(synonym(args).encode('utf-8', 'ignore')) | ||
else: | ||
print(synonym(args)) | ||
|
||
|
||
if __name__ == '__main__': | ||
command_line_runner() |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.