diff --git a/README.md b/README.md index 5b03546..e23c38d 100644 --- a/README.md +++ b/README.md @@ -11,11 +11,17 @@ or (или) ```python3 from yandexfreetranslate import YandexFreeTranslate yt = YandexFreeTranslate() +# yt.set_proxy("socks5", "localhost", 9050, "username", "password") print(yt.translate("en", "ru", "Hello, world!")) ``` Or from command line (Или из командной строки): ```bash +# for use socks4, socks5 or https proxy (Для использования socks4, socks5 или https proxy): +export https_proxy=127.0.0.1:9050 +# or (или) +export https_proxy=username:password@127.0.0.1:9050 + python3 yandexfreetranslate/__init__.py en ru "Hello, world!" # or (или) python3 yandexfreetranslate/__init__.py en ru in.txt diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..ea3b854 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +PySocks==1.7.1 diff --git a/setup.py b/setup.py index 1d8c9bf..08547d2 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ setup( name="yandexfreetranslate", - version="1.0", + version="1.1", author="alekssamos", author_email="aleks-samos@yandex.ru", url="https://github.com/alekssamos/yandexfreetranslate/", diff --git a/tests/test_translate.py b/tests/test_translate.py index 40f43c6..97fe0df 100644 --- a/tests/test_translate.py +++ b/tests/test_translate.py @@ -2,6 +2,8 @@ import os import os.path import re +import socks +from sockshandler import SocksiPyHandler import unittest try: import yandexfreetranslate @@ -10,6 +12,11 @@ import yandexfreetranslate del sys.path[0] +class dummy_build_opener(object): + h = None + def __init__(self, h=None): self.h = h + def open(self, *a, **k): return dummy_urlopen(*a, **k) + class dummy_urlopen(object): def __init__(self, url, *a, **kw): if type(url) == yandexfreetranslate.urllibrequest.Request: @@ -26,10 +33,16 @@ def read(self): raise ValueError("URL!") yandexfreetranslate.urllibrequest.urlopen = dummy_urlopen +yandexfreetranslate.urllibrequest.build_opener = dummy_build_opener class yt_test_translate(unittest.TestCase): def test_translate(self): yt = yandexfreetranslate.YandexFreeTranslate() + yt.set_proxy("socks5", "localhost", 9050) + self.assertTrue(yt.useProxy, True) + yt.useProxy = False + yt.set_proxy("https", "localhost", 9050) + self.assertTrue(yt.useProxy, True) self.assertTrue(len(yt.translate("en", "ru", "hello")) > 1) if __name__ == "__main__": diff --git a/tox.ini b/tox.ini index 3f6af60..907e650 100644 --- a/tox.ini +++ b/tox.ini @@ -9,6 +9,8 @@ skipsdist=true envlist = py36, py37, py38 [testenv] +deps = + PySocks commands = python -m unittest discover diff --git a/yandexfreetranslate/__init__.py b/yandexfreetranslate/__init__.py index 5219f57..a7ee07d 100644 --- a/yandexfreetranslate/__init__.py +++ b/yandexfreetranslate/__init__.py @@ -13,7 +13,11 @@ except ImportError: import urllib as urllibrequest import urllib as urllibparse - +sys.path.insert(0, os.path.dirname(__file__)) +import socks +try: from sockshandler import SocksiPyHandler +except ImportError: from .sockshandler import SocksiPyHandler +del sys.path[0] class YandexFreeTranslateError(Exception): pass @@ -25,19 +29,57 @@ class YandexFreeTranslate(): keysuffix = "-0-0" keyfilename = os.path.join(os.path.expanduser("~"), ".YandexFreeTranslate.key") expiretime = 60*60*24*4 + useProxy = False + proxy_protocol = "" + proxy_host = "" + proxy_port = 0 + proxy_username = "" + proxy_password = "" + def set_proxy(self, protocol, host, port, username="", password=""): + self.useProxy = True + self.proxy_protocol = protocol + self.proxy_host = host + self.proxy_port = int(port) + self.proxy_username = username + self.proxy_password = password + + def _create_opener(self): + opener = urllibrequest.build_opener() + if self.useProxy: + if self.proxy_protocol == "socks4": + opener = urllibrequest.build_opener(SocksiPyHandler(socks.SOCKS4, + self.proxy_host, self.proxy_port, username=self.proxy_username, password=self.proxy_password)) + if self.proxy_protocol == "socks5": + opener = urllibrequest.build_opener(SocksiPyHandler(socks.SOCKS5, + self.proxy_host, self.proxy_port, username=self.proxy_username, password=self.proxy_password)) + return opener + + def _create_request(self, *ar, **kw): + if len(ar) > 0 and "http" in ar[0]: url = ar[0] + if "url" in kw: url = kw["url"] + rq = urllibrequest.Request(*ar, **kw) + if self.useProxy: + if self.proxy_protocol == "http" or self.proxy_protocol == "https": + fullHost = ":".join([self.proxy_host, str(self.proxy_port)]) + if len(self.proxy_username) + len(self.proxy_password) > 0: + fullHost = ":".join([self.proxy_username, self.proxy_password]) + "@" + fullHost + rq.set_proxy(fullHost, self.proxy_protocol) + rq.add_header("Host", urllibparse.urlparse(url)[1]) + return rq + def _sid_to_key(self, sid): splitter = "." l = [] for item in sid.split(splitter): l.append(item[::-1]) return splitter.join(l)+self.keysuffix def _parse_sid(self): - req = urllibrequest.Request(self.siteurl) + req = self._create_request(self.siteurl) req.add_header("User-Agent", self.ua) req.add_header("Accept", r"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 ") req.add_header("Accept-Language", r"ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3") req.add_header("DNT", "1") req.add_header("Accept-Encoding", "gzip, deflate, br") - page = urllibrequest.urlopen(req).read().decode("UTF8") + page = self._create_opener().open(req).read().decode("UTF8") #open("page.html", "w", encoding="utf8").write(page) try: return re.search(r'''SID[\s]?[:][\s]?['"]([^'"]+)['"]''', page).group(1) @@ -75,7 +117,7 @@ def translate(self, source = "auto", target="", text=""): else: lang = source+"-"+target p=[] for part in smartsplit(text, 500, 550): - req = urllibrequest.Request(self.apibaseurl+"translate?"+urllibparse.urlencode({ + req = self._create_request(self.apibaseurl+"translate?"+urllibparse.urlencode({ "id":self.key, "srv":"tr-text", "lang":lang, "reason":"paste" })) req.add_header("User-Agent", self.ua) @@ -101,8 +143,23 @@ def translate(self, source = "auto", target="", text=""): print("usage: "+sys.argv[0]+" \t sourcelang \t targetlang \t text or file.txt \t [output_file_name.txt]") print('example: {0} "{1}" "{2}" "{3}"'.format(sys.argv[0], "en", "ru", "hello, world!")) print('example: {0} "{1}" "{2}" "{3}"'.format(sys.argv[0], "en", "ru", "in.txt")) + print("\n") + print("Install a proxy server: create an environment variable before calling:") + print("\t export https_proxy=127.0.0.1:8080") + print("\t export socks5_proxy=127.0.0.1:9050") + print("\t export socks5_proxy=username:password@127.0.0.1:9050") sys.exit(0) yt = YandexFreeTranslate() + for protocol in ["http", "https", "socks4", "socks5"]: + if protocol in os.environ: + if "@" in os.environ[protocol]: + auth, hostport = os.environ[protocol].split("@") + host, port = hostport.split(":") + login, password = auth.split(":") + else: + host, port = hostport.split(":") + login, password = ("", "") + yt.setProxy(protocol, host, port, login, password) text = sys.argv[3] if len(text) < 150 and os.path.isfile(text): text = open(text, "r", encoding="utf8").read() tr_text = yt.translate(sys.argv[1], sys.argv[2], text)