I'm developing an application that uses Google search for specific keywords on specific domains. However, scraping Google result page and parsing results from HTML is not very "clean" approach, so I switched to Custom Google Search API. I managed to fetch results for a single keyword so far, but but I'm having trouble getting results for multiple keywords and multiple domains. In the settings of Custom Search I set it to do a whole web search, just to mention. So, my question is, how can search for multiple keywords on specific domains without setting it in developers console?
Thanks in advance.
P.S. This is current code:
package org.wonderland.dev.java;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.customsearch.Customsearch;
import com.google.api.services.customsearch.model.Result;
import com.google.api.services.customsearch.model.Search;
public class GoogleSearchClient {
final private String API_KEY = "AIzaSyDxxxxxxxxxxxxxxxxxx";
final private String SEARCH_ENGINE_ID = "00844xxxxxxxxxx:xxxxxxxx";
public void printResults() {
String searchKeyWord = "app";
List<Result> resultList = this.getSearchResult(searchKeyWord);
if(resultList != null && resultList.size() > 0){
for(Result result: resultList){
System.out.println(result.getTitle());
}
}
}
public List<Result> getSearchResult(String keyword){
HttpTransport httpTransport = new NetHttpTransport();
JsonFactory jsonFactory = new JacksonFactory();
Customsearch customsearch = new Customsearch(httpTransport, jsonFactory,null);
List<Result> resultList = null;
try {
Customsearch.Cse.List list = customsearch.cse().list(keyword);
list.setKey(API_KEY);
list.setCx(SEARCH_ENGINE_ID);
list.setNum(10L);
Search results = list.execute();
resultList = results.getItems();
} catch (Exception e) {
e.printStackTrace();
}
return resultList;
}
}
Related
Tried going through the internet and google docs they provide OAuth way only. Is there a way to read/write to google sheets with API Key and not OAuth.
After some research, Credential object from google-oath-client module can help. Download the .p12 file from the google account. Code for reading a google sheet without OAUth prompt below. This can also be used to write or append sheets with some modification :
package com.mycomp;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.sheets.v4.Sheets;
import com.google.api.services.sheets.v4.SheetsScopes;
import com.google.api.services.sheets.v4.model.ValueRange;
import com.nm.vernacular.services.SpreadSheetsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
/**
* Created by ankushgupta & modified for SO.
*/
public class GoogleSheetsReader {
private static final JsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance();
private static final String KEY_FILE_LOCATION = "<Name of p12 file>.p12";
private static final String SERVICE_ACCOUNT_EMAIL = "<email of google service account>";
private static final String APPLICATION_NAME = "Google Sheets API";
private static final Logger LOGGER = LoggerFactory.getLogger(GoogleSheetsReader.class);
/**
* Global instance of the scopes required by this quickstart.
* If modifying these scopes, delete your previously saved credentials/ folder.
*/
private static final List<String> SCOPES = Collections.singletonList(SheetsScopes.SPREADSHEETS);
/**
* Creates an authorized Credential object.
* #return An authorized Credential object.
* #throws IOException If there is no client_secret.
*/
private Credential getCredentials() throws URISyntaxException, IOException, GeneralSecurityException {
//Reading Key File
URL fileURL = GoogleSheetsReader.class.getClassLoader().getResource(KEY_FILE_LOCATION);
// Initializes an authorized analytics service object.
if(fileURL==null) {
fileURL = (new File("/resources/"+ KEY_FILE_LOCATION)).toURI().toURL();
}
// Construct a GoogleCredential object with the service account email
// and p12 file downloaded from the developer console.
HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
return new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountPrivateKeyFromP12File(new File(fileURL.toURI()))
.setServiceAccountScopes(SCOPES)
.build();
}
#Override
public List<Object[]> readSheet(String nameAndRange, String key, int[] returnRange) throws GeneralSecurityException, IOException {
final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
final String spreadsheetId = key;
final String range = nameAndRange;
try {
Sheets service = new Sheets.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredentials())
.setApplicationName(APPLICATION_NAME)
.build();
ValueRange response = service.spreadsheets().values()
.get(spreadsheetId, range)
.execute();
List<List<Object>> values = response.getValues();
int a = returnRange.length;
List<Object[]> result = new LinkedList<>();
if (values == null || values.isEmpty()) {
return Collections.emptyList();
} else {
for (List row : values) {
if(row.size() >= a) {
Object[] objArr = new Object[a];
for(int i=0;i<a;i++) {
objArr[i] = row.get(returnRange[i]);
}
result.add(objArr);
}
}
}
return result;
} catch(Exception ex) {
LOGGER.error("Exception while reading google sheet", ex);
} finally {
}
return null;
}
public static void main(String[] args) {
GoogleSheetsReader reader = new GoogleSheetsReader();
reader.readSheet("<Sheet Name>!A2:B", "<sheets key from URL>", new int[]{0, 1});
}
}
Based from this documentation, when your application requests public data, the request doesn't need to be authorized, but does need to be accompanied by an identifier, such as an API key.
Every request your application sends to the Google Sheets API needs to identify your application to Google. There are two ways to identify your application: using an OAuth 2.0 token (which also authorizes the request) and/or using the application's API key. Here's how to determine which of those options to use:
If the request requires authorization (such as a request for an individual's private data), then the application must provide an OAuth 2.0 token with the request. The application may also provide the API key, but it doesn't have to.
If the request doesn't require authorization (such as a request for public data), then the application must provide either the API key or an OAuth 2.0 token, or both—whatever option is most convenient for you.
However, there are some scopes which require OAuth authorization. Check this link: Access Google spreadsheet API without Oauth token.
Using API key, you can read from google sheets, but only if the sheet is shared with public.
However to write to google sheets, you must you OAuth. See this link.
I am using Google Bigquery V2 Java API. I am not able to find a way to get query results in JSON format.
In Bigquery Web UI we can see this JSON and Table form of results. see scrrenshot.
Is there any way to get the GetQueryResultsResponse as JSON, using Java API.
One option is to apply the TO_JSON_STRING function to the results of your query. For example,
#standardSQL
SELECT TO_JSON_STRING(t)
FROM (
SELECT x, y
FROM YourTable
WHERE z = 10
) AS t;
If you want all of the table's columns as JSON, you can use a simpler form:
#standardSQL
SELECT TO_JSON_STRING(t)
FROM YourTable AS t
WHERE z = 10;
I'm using a service account to access the BigQuery REST API to get the response in JSON format.
In order to use a service account, you will have to go to credentials (https://console.cloud.google.com/apis/credentials) and choose a project.
You will get a drop down like this:
Create a Service account for your project and download the secret file in the JSON format. Keep the JSON file in your file system and set the path to it. Check below image to set the file path:
So, now all you have to do in is use JAVA client api to consume the Big Query REST API.
Here's is a simple solution that I've been using for my project.
package com.example.bigquery;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import org.apache.log4j.Logger;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpContent;
import com.google.api.client.http.HttpHeaders;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestFactory;
import com.google.api.client.http.HttpResponse;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.http.json.JsonHttpContent;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.common.io.CharStreams;
public class BigQueryDemo {
private static final String QUERY_URL_FORMAT = "https://www.googleapis.com/bigquery/v2/projects/%s/queries" + "?access_token=%s";
private static final String QUERY = "query";
private static final String QUERY_HACKER_NEWS_COMMENTS = "SELECT * FROM [bigquery-public-data:hacker_news.comments] LIMIT 1000";
private static final Logger logger = Logger.getLogger(BigQueryDemo.class);
static GoogleCredential credential = null;
static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
static final JsonFactory JSON_FACTORY = new JacksonFactory();
static {
// Authenticate requests using Google Application Default credentials.
try {
credential = GoogleCredential.getApplicationDefault();
credential = credential.createScoped(Arrays.asList("https://www.googleapis.com/auth/bigquery"));
credential.refreshToken();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void implicit() {
String projectId = credential.getServiceAccountProjectId();
String accessToken = generateAccessToken();
// Set the content of the request.
Dataset dataset = new Dataset().addLabel(QUERY, QUERY_HACKER_NEWS_COMMENTS);
HttpContent content = new JsonHttpContent(JSON_FACTORY, dataset.getLabels());
// Send the request to the BigQuery API.
GenericUrl url = new GenericUrl(String.format(QUERY_URL_FORMAT, projectId, accessToken));
logger.debug("URL: " + url.toString());
String responseJson = getQueryResult(content, url);
logger.debug(responseJson);
}
private static String getQueryResult(HttpContent content, GenericUrl url) {
String responseContent = null;
HttpRequestFactory requestFactory = HTTP_TRANSPORT.createRequestFactory();
HttpRequest request = null;
try {
request = requestFactory.buildPostRequest(url, content);
request.setParser(JSON_FACTORY.createJsonObjectParser());
request.setHeaders(
new HttpHeaders().set("X-HTTP-Method-Override", "POST").setContentType("application/json"));
HttpResponse response = request.execute();
InputStream is = response.getContent();
responseContent = CharStreams.toString(new InputStreamReader(is));
} catch (IOException e) {
logger.error(e);
}
return responseContent;
}
private static String generateAccessToken() {
String accessToken = null;
if ((System.currentTimeMillis() > credential.getExpirationTimeMilliseconds())) {
accessToken = credential.getRefreshToken();
} else {
accessToken = credential.getAccessToken();
}
System.out.println(accessToken);
return accessToken;
}
}
Following is the Github link to the code: https://github.com/vslala/BigQueryRestSample
It is just a demo project to fetch JSON data from the BQ REST API. Do not use it in your project directly.
Let me know if you have any questions.
I'm trying to generate a list of all my saved reddit items using JRAW.
I've gone through the Quickstart , and successfully managed to login and retrieve information, and I can get a list of items on the Frontpage from the Cookbook, but I can't work out how I would get a list of my saved items (comments and posts) or a list of my own posts (also comments and posts).
The saved items are at https://www.reddit.com/user/<username>/saved/, but I don't know how to get jraw to retrieve and parse that, or if the api uses a different URL.
Edit: I think I probably need to use a UserContributionPaginator, but I haven't quite worked out exactly how to get it to work yet.
Worked it out.
package com.jraw;
import net.dean.jraw.RedditClient;
import net.dean.jraw.http.UserAgent;
import net.dean.jraw.http.oauth.Credentials;
import net.dean.jraw.http.oauth.OAuthData;
import net.dean.jraw.http.oauth.OAuthException;
import net.dean.jraw.models.Contribution;
import net.dean.jraw.models.Listing;
import net.dean.jraw.paginators.UserContributionPaginator;
public class printSaved {
public static void main(String [] args) {
UserAgent myUserAgent = UserAgent.of("desktop", "com.jraw.printSaved", "v0.01", "user");
RedditClient redditClient = new RedditClient(myUserAgent);
String username = "username";
Credentials credentials = Credentials.script(username, "<password>", "<clientId>", "<clientSecret>");
OAuthData authData = null;
try {
authData = redditClient.getOAuthHelper().easyAuth(credentials);
} catch (OAuthException e) {
e.printStackTrace();
}
redditClient.authenticate(authData);
UserContributionPaginator saved = new UserContributionPaginator(redditClient,"saved",username);
Listing<Contribution> savedList = saved.next();
for (Contribution item : savedList) {
System.out.println(item);
}
}
}
I'm trying to use the Google Custom Search API to, obviously, search in google. I've made this Java Agent in Lotus Notes.
The Main Class:
import java.util.List;
import lotus.domino.AgentBase;
import com.google.api.services.customsearch.model.Result;
public class JavaAgent extends AgentBase {
public void NotesMain() {
GoogleSearchClient gsc = new GoogleSearchClient();
String searchKeyWord = "test";
List<Result> resultList = gsc.getSearchResult(searchKeyWord);
if(resultList != null && resultList.size() > 0){
for(Result result: resultList){
System.out.println(result.getHtmlTitle());
System.out.println(result.getFormattedUrl());
System.out.println("----------------------------------------");
}
}
}
}
And that's the GoogleSearchClient class:
import java.util.Collections;
import java.util.List;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.services.customsearch.Customsearch;
import com.google.api.services.customsearch.model.Result;
import com.google.api.services.customsearch.model.Search;
public class GoogleSearchClient {
public List<Result> getSearchResult(String keyword){
String GOOGLE_SEARCH_URL = https://www.googleapis.com/customsearch/v1?";
//api key
String API_KEY = "xxxxxxxxxxxxxxxxxxxxx";
//custom search engine ID
String SEARCH_ENGINE_ID = "xxxxxxxxxx:xxxxxxxxxxxx";
String FINAL_URL= GOOGLE_SEARCH_URL + "key=" + API_KEY + "&cx=" + SEARCH_ENGINE_ID;
// Set up the HTTP transport and JSON factory
HttpTransport httpTransport = new NetHttpTransport();
JsonFactory jsonFactory = new com.google.api.client.json.jackson2.JacksonFactory();
//HttpRequestInitializer initializer = (HttpRequestInitializer)new CommonGoogleClientRequestInitializer(API_KEY);
Customsearch customsearch = new Customsearch(httpTransport, jsonFactory,null);
List<Result> resultList = Collections.emptyList();
try {
Customsearch.Cse.List list = customsearch.cse().list(keyword);
list.setKey(API_KEY);
list.setCx(SEARCH_ENGINE_ID);
//num results per page
//list.setNum(2L);
//for pagination
list.setStart(10L);
Search results = list.execute();
resultList = results.getItems();
}catch (Exception e) {
e.printStackTrace();
}
return resultList;
}
}
I've got the code here.
This returns me this Exception:
java.security.AccessControlException: Access denied (java.lang.reflect.ReflectPermission suppressAccessChecks)
at java.security.AccessController.throwACE(AccessController.java:100)
at java.security.AccessController.checkPermission(AccessController.java:174)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:544)
at COM.ibm.JEmpower.applet.AppletSecurity.superDotCheckPermission(AppletSecurity.java:1449)
at COM.ibm.JEmpower.applet.AppletSecurity.checkPermission(AppletSecurity.java:1617)
at COM.ibm.JEmpower.applet.AppletSecurity.checkPermission(AppletSecurity.java:1464)
at java.lang.reflect.AccessibleObject.setAccessible(AccessibleObject.java:118)
at com.google.api.client.util.FieldInfo.of(FieldInfo.java:97)
at com.google.api.client.util.ClassInfo.<init>(ClassInfo.java:172)
at com.google.api.client.util.ClassInfo.of(ClassInfo.java:90)
at com.google.api.client.util.GenericData.<init>(GenericData.java:79)
at com.google.api.client.util.GenericData.<init>(GenericData.java:61)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.<init>(AbstractGoogleClientRequest.java:109)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.<init>(AbstractGoogleJsonClientRequest.java:57)
at com.google.api.services.customsearch.CustomsearchRequest.<init>(CustomsearchRequest.java:43)
at com.google.api.services.customsearch.Customsearch$Cse$List.<init>(Customsearch.java:178)
at com.google.api.services.customsearch.Customsearch$Cse.list(Customsearch.java:154)
at GoogleSearchClient.getSearchResult(Unknown Source)
at JavaAgent.NotesMain(Unknown Source)
at lotus.domino.AgentBase.runNotes(Unknown Source)
at lotus.domino.NotesThread.run(Unknown Source)
I've digged this Exception in the internet and I've understood that the JVM doesn't think that I have the privileges and tried some things.
I added this permissions below in the "Java.policy" archive in my local machine and in the server, but it doesn't work.
grant { permission java.util.PropertyPermission "http.keepAlive", "read, write"; };
grant { permission java.security.AllPermission; }
I would try this but my Software Version is 9.
I tryed this same code in Eclipse and it worked just fine, so I think that's a Notes Security configuration that is wrong. I have to do in Lotus Notes because I have to save the informations in forms etc.
I changed the Runtime security Level to 3 (Allow restricted operations with full administration rights)
Any ideas that how can I go through this?
When I was working on WS-Security for my Web Service Consumer in Lotus, I got the same error. I found out that I can avoid this by using AccessController.doPrivileged method in my .jar file. So, you need to create separate .jar in your IDE and use it in your Lotus Agent.
Here is example of using AccessController.doPrivileged with your code:
import java.util.Collections;
import java.util.List;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.services.customsearch.Customsearch;
import com.google.api.services.customsearch.model.Result;
import com.google.api.services.customsearch.model.Search;
public class GoogleSearchClient {
public List<Result> getSearchResult(final String keyword){
String GOOGLE_SEARCH_URL = https://www.googleapis.com/customsearch/v1?";
//api key
final String API_KEY = "xxxxxxxxxxxxxxxxxxxxx";
//custom search engine ID
final String SEARCH_ENGINE_ID = "xxxxxxxxxx:xxxxxxxxxxxx";
String FINAL_URL= GOOGLE_SEARCH_URL + "key=" + API_KEY + "&cx=" + SEARCH_ENGINE_ID;
// Set up the HTTP transport and JSON factory
HttpTransport httpTransport = new NetHttpTransport();
JsonFactory jsonFactory = new com.google.api.client.json.jackson2.JacksonFactory();
//HttpRequestInitializer initializer = (HttpRequestInitializer)new CommonGoogleClientRequestInitializer(API_KEY);
final Customsearch customsearch = new Customsearch(httpTransport, jsonFactory,null);
return AccessController.doPrivileged(
new PrivilegedAction<List<Result>>() {
#Override
public List<Result> run() {
List<Result> resultList = Collections.emptyList();
try {
Customsearch.Cse.List list = customsearch.cse().list(keyword);
list.setKey(API_KEY);
list.setCx(SEARCH_ENGINE_ID);
//num results per page
//list.setNum(2L);
//for pagination
list.setStart(10L);
Search results = list.execute();
resultList = results.getItems();
}catch (Exception e) {
e.printStackTrace();
}
return resultList;
}
});
}
}
I am running the YouTubeSample given on the google developers website. I have no errors in the code and my imports appear to be fine. But when I run the project I get the aforementioned error.
I have done some searches but to be honest I have been unable to work out what the problem is. I have already tried importing an external jar guava but it didn't help.
Any help is appreciated. Here is the full class
package com.pengilleys.googlesamples;
import java.io.IOException;
import java.util.List;
import com.google.api.client.googleapis.GoogleHeaders;
import com.google.api.client.googleapis.json.JsonCParser;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestFactory;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson.JacksonFactory;
import com.google.api.client.util.Key;
public class YouTubeSample {
public static class VideoFeed {
#Key List<Video> items;
}
public static class Video {
#Key String title;
#Key String description;
#Key Player player;
}
public static class Player {
#Key("default") String defaultUrl;
}
public static class YouTubeUrl extends GenericUrl {
#Key final String alt = "jsonc";
#Key String author;
#Key("max-results") Integer maxResults;
YouTubeUrl(String url) {
super(url);
}
}
public static void main(String[] args) throws IOException {
// set up the HTTP request factory
HttpTransport transport = new NetHttpTransport();
final JsonFactory jsonFactory = new JacksonFactory();
HttpRequestFactory factory = transport.createRequestFactory(new HttpRequestInitializer() {
#Override
public void initialize(HttpRequest request) {
// set the parser
JsonCParser parser = new JsonCParser();
parser.jsonFactory = jsonFactory;
request.addParser(parser);
// set up the Google headers
GoogleHeaders headers = new GoogleHeaders();
headers.setApplicationName("Google-YouTubeSample/1.0");
headers.gdataVersion = "2";
request.headers = headers;
}
});
// build the YouTube URL
YouTubeUrl url = new YouTubeUrl("https://gdata.youtube.com/feeds/api/videos");
url.author = "searchstories";
url.maxResults = 2;
// build the HTTP GET request
HttpRequest request = factory.buildGetRequest(url);
// execute the request and the parse video feed
VideoFeed feed = request.execute().parseAs(VideoFeed.class);
for (Video video : feed.items) {
System.out.println();
System.out.println("Video title: " + video.title);
System.out.println("Description: " + video.description);
System.out.println("Play URL: " + video.player.defaultUrl);
}
}
}
The setup documentation gives a list of dependencies:
Depending on the application you are building, you may also need these dependencies:
Apache HTTP Client version 4.0.3
Google Guava version r09
Jackson version 1.6.7
Google GSON version 1.6
In this case, it looks like it's Guava which is missing. I don't know what you mean about "exporting" Guava, but if you include the Guava r09 jar file in the classpath when you're running the code, it should be fine.
what's the extra ); for above the // build the YouTube URL and did you mean to close main on that line?