| 1016 | RE_GOOGLE_DATE = re.compile("^([A-Z][a-z]{2} [0-9]{1,2}, [0-9]{4}) {0,1}...") |
| 1017 | |
| 1018 | class Google(SearchEngine): |
| 1019 | |
| 1020 | def __init__(self, license=None, throttle=0.5, language=None): |
| 1021 | SearchEngine.__init__(self, license or GOOGLE_LICENSE, throttle, language) |
| 1022 | |
| 1023 | def search(self, query, type=SEARCH, start=1, count=10, sort=RELEVANCY, size=None, cached=True, **kwargs): |
| 1024 | """ Returns a list of results from Google for the given query. |
| 1025 | - type : SEARCH, |
| 1026 | - start: maximum 100 results => start 1-10 with count=10, |
| 1027 | - count: maximum 10, |
| 1028 | There is a daily limit of 10,000 queries. Google Custom Search is a paid service. |
| 1029 | """ |
| 1030 | if type != SEARCH: |
| 1031 | raise SearchEngineTypeError |
| 1032 | if not query or count < 1 or start < 1 or start > (100 / count): |
| 1033 | return Results(GOOGLE, query, type) |
| 1034 | # 1) Create request URL. |
| 1035 | url = URL(GOOGLE, query={ |
| 1036 | "key": self.license or GOOGLE_LICENSE, |
| 1037 | "cx": GOOGLE_CUSTOM_SEARCH_ENGINE, |
| 1038 | "q": query, |
| 1039 | "start": 1 + (start-1) * count, |
| 1040 | "num": min(count, 10), |
| 1041 | "alt": "json" |
| 1042 | }) |
| 1043 | # 2) Restrict language. |
| 1044 | if self.language is not None: |
| 1045 | url.query["lr"] = "lang_" + self.language |
| 1046 | # 3) Parse JSON response. |
| 1047 | kwargs.setdefault("unicode", True) |
| 1048 | kwargs.setdefault("throttle", self.throttle) |
| 1049 | data = url.download(cached=cached, **kwargs) |
| 1050 | data = json.loads(data) |
| 1051 | if data.get("error", {}).get("code") == 403: |
| 1052 | raise SearchEngineLimitError |
| 1053 | results = Results(GOOGLE, query, type) |
| 1054 | results.total = int(data.get("queries", {}).get("request", [{}])[0].get("totalResults") or 0) |
| 1055 | for x in data.get("items", []): |
| 1056 | r = Result(url=None) |
| 1057 | r.url = self.format(x.get("link")) |
| 1058 | r.title = self.format(x.get("title")) |
| 1059 | r.text = self.format(x.get("htmlSnippet").replace("<br> ","").replace("<b>...</b>", "...")) |
| 1060 | r.language = self.language or "" |
| 1061 | r.date = "" |
| 1062 | if not r.date: |
| 1063 | # Google Search results can start with a date (parsed from the content): |
| 1064 | m = RE_GOOGLE_DATE.match(r.text) |
| 1065 | if m: |
| 1066 | r.date = m.group(1) |
| 1067 | r.text = "..." + r.text[len(m.group(0)):] |
| 1068 | results.append(r) |
| 1069 | return results |
| 1070 | |
| 1071 | def translate(self, string, input="en", output="fr", **kwargs): |
| 1072 | """ Returns the translation of the given string in the desired output language. |
| 1073 | Google Translate is a paid service, license without billing raises HTTP401Authentication. |
| 1074 | """ |
| 1075 | url = URL("https://www.googleapis.com/language/translate/v2?", method=GET, query={ |
no outgoing calls
no test coverage detected
searching dependent graphs…