static L> quickGoogle2(S query) { ret quickGoogle2(query, "lang_en"); } static L> quickGoogle2(S query, S language) { query = trim(query); L> out = lookupPossiblyIgnoringCase(parseGoogleLog(), query); if (out != null) ret out; out = new L; S userAgent = "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:53.0) Gecko/20100101 Firefox/53.0"; S html = loadPageWithUserAgent("https://www.google.com/search?q=" + urlencode(query) + "&lr=" + language + "&hl=en", userAgent); S url = first(loadPage_responseHeaders->get("Location")); if (url != null) html = loadPageWithUserAgent(url, userAgent); L htmlTok = htmlTok(html); LL h3s = findContainerTagDeep(htmlTok, "h3"); for (L tok : h3s) { L linkTok = first(findContainerTag(tok, "a")); if (empty(linkTok)) continue; S link = tagGet(second(linkTok), "href"); continue unless isAbsoluteURL(link); S text = htmldecode(join(dropTags(contentsOfContainerTag(linkTok)))); L sub = subList(htmlTok, magicIndexOfSubList(htmlTok, tok)+l(tok)-1); S desc = trim(htmldecode(dropTags(join(first(findContainerTagWithParams(sub, "span", "class" := "st")))))); out.add(triple(link, text, desc)); } logStructure(googleLog(), litorderedmap(+query, +language, date := localDateWithSeconds(), results := out)); ret out; }