Skip to content

Commit

Permalink
g-i-s but async / awaitable
Browse files Browse the repository at this point in the history
  • Loading branch information
ThamosIO committed May 10, 2020
1 parent 5d2845f commit d4a8955
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 73 deletions.
37 changes: 13 additions & 24 deletions README.md
@@ -1,29 +1,20 @@
g-i-s
=====
# g-i-s

[![Build Status](https://travis-ci.org/jimkang/g-i-s.svg?branch=master)](https://travis-ci.org/jimkang/g-i-s)

Another Google Image Search Node module. The nature of these things is that they eventually break as GIS changes, but this one works as of 2018-06-20.

Installation
------------
## Installation

npm install g-i-s

Usage
-----
## Usage

var gis = require('g-i-s');
gis('cats', logResults);
const gis = require('g-i-s');
const { error, results } = await gis('cats');

function logResults(error, results) {
if (error) {
console.log(error);
}
else {
console.log(JSON.stringify(results, null, ' '));
}
}
console.log(error);
console.log(JSON.stringify(results, null, ' '));

Output:

Expand Down Expand Up @@ -53,33 +44,31 @@ Output:

If you want to pass additional stuff to tack onto the Google image search URL, pass an object containing `searchTerm` and `queryStringAddition`. e.g.

var opts = {
const opts = {
searchTerm: 'cat',
queryStringAddition: '&tbs=ic:trans'
};
gis(opts, logResults);
const { results } = await gis(opts);

You can also filter out results from specfied domains:

var opts = {
const opts = {
searchTerm: 'cat',
queryStringAddition: '&tbs=ic:trans',
filterOutDomains: [
'pinterest.com',
'deviantart.com'
]
};
gis(opts, logResults);
const { results } = await gis(opts);

Specifying `filterOutDomains` will both tell Google to not to include results that come from web pages on those domains and also filter image results that are hosted on those domains. (Sometimes an image is on an html page on a domain not included in your filters and has an img tag that loads from a domain that is included in your filters.)

Tests
-----
## Tests

Run tests with `make test`.

License
-------
## License

The MIT License (MIT)

Expand Down
72 changes: 37 additions & 35 deletions index.js
@@ -1,16 +1,16 @@
var request = require('request');
var cheerio = require('cheerio');
var queryString = require('querystring');
var flatten = require('lodash.flatten');
const fetch = require('node-fetch');
const cheerio = require('cheerio');
const queryString = require('querystring');
const flatten = require('lodash.flatten');

var baseURL = 'http://images.google.com/search?';
const baseURL = 'http://images.google.com/search?';

var imageFileExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.svg'];
const imageFileExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.svg'];

function gis(opts, done) {
var searchTerm;
var queryStringAddition;
var filterOutDomains = ['gstatic.com'];
async function gis(opts, done) {
let searchTerm;
let queryStringAddition;
let filterOutDomains = ['gstatic.com'];

if (typeof opts === 'string') {
searchTerm = opts;
Expand All @@ -20,11 +20,11 @@ function gis(opts, done) {
filterOutDomains = filterOutDomains.concat(opts.filterOutDomains);
}

var url =
let url =
baseURL +
queryString.stringify({
tbm: 'isch',
q: searchTerm
q: searchTerm,
});

if (filterOutDomains) {
Expand All @@ -36,26 +36,28 @@ function gis(opts, done) {
if (queryStringAddition) {
url += queryStringAddition;
}
var reqOpts = {
url: url,
headers: {
'User-Agent':
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36'
}

const headers = {
'User-Agent':
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36',
};
let res;
let results;

try {
res = await fetch(url, { headers });
results = await res.text();
} catch (e) {
return { error: e };
}

// console.log(reqOpts.url);
request(reqOpts, parseGISResponse);
return parseGISResponse(results);

function parseGISResponse(error, response, body) {
if (error) {
done(error);
return;
}
var $ = cheerio.load(body);
var scripts = $('script');
var scriptContents = [];
for (var i = 0; i < scripts.length; ++i) {
function parseGISResponse(images) {
const $ = cheerio.load(images);
const scripts = $('script');
const scriptContents = [];
for (let i = 0; i < scripts.length; ++i) {
if (scripts[i].children.length > 0) {
const content = scripts[i].children[0].data;
if (containsAnyImageFileExtension(content)) {
Expand All @@ -64,18 +66,18 @@ function gis(opts, done) {
}
}

done(error, flatten(scriptContents.map(collectImageRefs)));
return flatten(scriptContents.map(collectImageRefs));

function collectImageRefs(content) {
var refs = [];
var re = /\["(http.+?)",(\d+),(\d+)\]/g;
var result;
const refs = [];
const re = /\["(http.+?)",(\d+),(\d+)\]/g;
let result;
while ((result = re.exec(content)) !== null) {
if (result.length > 3) {
let ref = {
url: result[1],
width: +result[2],
height: +result[3]
height: +result[3],
};
if (domainIsOK(ref.url)) {
refs.push(ref);
Expand Down Expand Up @@ -104,7 +106,7 @@ function addSiteExcludePrefix(s) {
}

function containsAnyImageFileExtension(s) {
var lowercase = s.toLowerCase();
const lowercase = s.toLowerCase();
return imageFileExtensions.some(containsImageFileExtension);

function containsImageFileExtension(ext) {
Expand Down
5 changes: 5 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "g-i-s",
"version": "2.1.5",
"version": "3.0.0",
"description": "Google Image Search",
"main": "index.js",
"scripts": {
Expand All @@ -23,6 +23,7 @@
"dependencies": {
"cheerio": "^1.0.0-rc.3",
"lodash.flatten": "^4.4.0",
"node-fetch": "^2.6.0",
"request": "^2.88.2"
}
}
25 changes: 12 additions & 13 deletions tests/basictests.js
Expand Up @@ -7,28 +7,27 @@ var searchTopics = [
'ківі',
{
searchTerm: 'sleep',
queryStringAddition: '&tbs=ic:trans'
queryStringAddition: '&tbs=ic:trans',
},
{
searchTerm: 'pony',
queryStringAddition: '&tbs=ic:trans',
filterOutDomains: ['deviantart.net', 'deviantart.com']
}
filterOutDomains: ['deviantart.net', 'deviantart.com'],
},
];

searchTopics.forEach(runTest);

function runTest(topic) {
test('Basic test', function basicTest(t) {
gis(topic, checkResults);
async function runTest(topic) {
test('Basic test', async (t) => {
const lol = await gis(topic);
const { error = null, results = [] } = lol;

function checkResults(error, results) {
t.ok(!error, 'No error.');
t.ok(results.length > 0, 'There is at least one result.');
results.forEach(checkResult);
// console.log(JSON.stringify(results, null, ' '));
t.end();
}
t.ok(!error, 'No error.');
t.ok(results.length > 0, 'There is at least one result.');
results.forEach(checkResult);

t.end();

function checkResult(result) {
t.equal(typeof result, 'object', 'Result is an object.');
Expand Down

0 comments on commit d4a8955

Please sign in to comment.