How to extract data from Facebook pages using FQL in Java - java

I want to extract data such as name of page, likes,talking_about_count and page information from any page using FQL in Java. I have written code like below:
public static void main(String[] args) {
// TODO Auto-generated method stub
String STR_FACEBOOK_FQL_URL = "https://api.facebook.com/method/fql.query?query=";
String STR_FACEBOOK_RETURN_FORMAT = "&format=json";
String STR_FACEBOOK_ACCESS_TOKEN = "&access_token=";
String FQL_GET_QUERY= "SELECT name,likes,about FROM page WHERE id={page-id}";
String encodedQuery;
try
{
encodedQuery = URLEncoder.encode(FQL_GET_QUERY, "UTF-8");
String faceBookURL = STR_FACEBOOK_FQL_URL + encodedQuery +
STR_FACEBOOK_RETURN_FORMAT
+ STR_FACEBOOK_ACCESS_TOKEN ;
URL url = new URL(faceBookURL);
InputStream is = url.openStream();
JSONTokener tok = new JSONTokener(is);
JSONObject result = new JSONObject(tok);
System.out.println(result.toString());
is.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
But this is shownig error like:
{"request_args":[{"value":"fql.query","key":"method"},{"value":"SELECT likes,name,about FROM page WHERE uid=me()","key":"query"},{"value":"json","key":"format"},{"value":"id|secret","key":"access_token"}],"error_code":602,"error_msg":"likes is not a member of the page table."}
Can anybody tell me, what is the wrong in this code?

First of all, please don't use the deprecated endpoint:
String STR_FACEBOOK_FQL_URL = "https://graph.facebook.com/fql?q=";
is the way to go now. You're using non-existing fields for the page table (see https://developers.facebook.com/docs/reference/fql/page/). likes needs to be replaced by fan_count:
String FQL_GET_QUERY= "SELECT name,fan_count,about FROM page WHERE id={page-id}";

Related

How to return JSON response from a URL returning HTML

First, some background :-
I'm trying to solve a question asked by an interviewer recently. I had to write a code and use below URL to return JSON response -
https://losangeles.craigslist.org/
This is what I did :-
1) I created a webclient and made HTTPURL Request to fetch an HTTP Response.
public static JSONArray getSearchResults(String arg) {
JSONArray jsonArray = null;
try {
QueryString qs = new QueryString("query", arg);
URL url = new URL("https://toronto.craigslist.ca/search?"+qs);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept", "application/text");
if (conn.getResponseCode() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ conn.getResponseCode());
}
BufferedReader br = new BufferedReader(new InputStreamReader(
(conn.getInputStream())));
String readAPIResponse = " ";
StringBuilder output = new StringBuilder();
while ((readAPIResponse = br.readLine()) != null) {
output.append(readAPIResponse);
}
jsonArray = convertToJson(output);
System.out.println(" JSON response : "+jsonArray.toString(2));
conn.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return jsonArray;
}
2) Below was my function to convert the response into JSON :-
public static JSONArray convertToJson(StringBuilder response) {
JSONArray jsonArr = new JSONArray();
if (response != null) {
try {
Document document = Jsoup.parse(response.toString());
Elements resultRows = document.getElementsByClass("result-row");
JSONObject jsonObj;
for (int i = 0; i < resultRows.size(); i++) {
jsonObj = new JSONObject();
Element e = resultRows.get(i);
Elements resultsDate = e.getElementsByClass("result-date");
Elements resultsTitle = e.getElementsByClass("result-title hdrlnk");
String key1 = "date";
String value1 = resultsDate.get(0).text();
jsonObj.put(key1, value1);
String key2 = "title";
String value2 = resultsTitle.get(0).text();
jsonObj.put(key2, value2);
jsonArr.put(i, jsonObj);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
return jsonArr;
}
The response I received was the whole HTML page(I used postman to make requests). Since, I only had few hours to solve this question and was not sure how to parse an entire HTML, I ended up using a third party library, called JSoup. I was not 100% happy about it, but ended up having no other option.
I have not heard back from them and I am curious if this was the worst approach and if yes, what could be better options? They did not mention anything about what technology I could use. But,since the skill set I was interviewing involved Java/J2EE I was thinking to implement this in Java (Not using Node js though)
Thanks!
If you only need an XML Parser which is obviously the base of HTML this is built in in the JRE core API.
Even in the SE Version the needed packages to parse exist:
import org.w3c.dom.*;
import javax.xml.parsers.*;
import java.io.*;
Take a look at these classes they are the most important to parse or create an XML/HTML File
DocumentBuilderFactory
DocumentBuilder
Document
and here simple example for HTML
String text = "<html><head>HEAD</head><body>BODY</body>";
ByteArrayInputStream input = new ByteArrayInputStream(text.getBytes("UTF-8"));
Document doc = builder.parse(input);

Java Eclipse - 'Unexpected token END OF FILE at position 0' when trying to read from JSON

I am using Java Eclipse to create an event management system which will write and read JSON files. Here I have code which creates a new JSON file...
public void actionPerformed(ActionEvent arg0) {
//Declaration of variables
String title = txtTitle.getText();
String month = (String) cboMonth.getSelectedItem();
String day = (String) cboDate.getSelectedItem();
String year = (String) cboYear.getSelectedItem();
String location = txtLocation.getText();
String description = txtDescription.getText();
String URL = txtURL.getText();
// Combine multiple variables together to make a single variable
String date = month + "" + day + "" + year;
// Create a new instance of the class called 'Event'
Event event = new Event();
// Assign values to the getter/setter methods of this instance
event.setName(title);
event.setDate(date);
event.setLocation(location);
event.setDesc(description);
event.setURL(URL);
// Add this new instance to the 'eventList' array list
MainMenu.eventList.add(event);
// Create a new instance of the class called 'Event'
JSONObject JSONEvent = new JSONObject();
// Add data to the JSON file
JSONEvent.put("Title", title);
JSONEvent.put("Date", date);
JSONEvent.put("Location", location);
JSONEvent.put("Description", description);
JSONEvent.put("URL", URL);
// Create a new JSON file called 'Events.json' that has elements added to it
try (FileWriter file = new FileWriter("Events.json", true)) {
file.write("\n");
file.write(JSONEvent.toJSONString());
file.flush();
// Error Handling
} catch (IOException e) {
e.printStackTrace();
}
}
This code works perfectly fine by creating a JSON file and populating it with JSONObjects. Here is an image of what a single entry in the JSON file looks like... Single JSON Element
I then have a separate class with the following code which attempts to read the JSON file and output its contents to the console...
public static void main(String[] args) {
JSONObject JSONEvent;
String line = null;
try {
FileReader fileReader = new FileReader("Events.json");
BufferedReader bufferedReader = new BufferedReader(fileReader);
while((line = bufferedReader.readLine()) != null) {
JSONEvent = (JSONObject) new JSONParser().parse(line);
String title = (String) JSONEvent.get("Title");
System.out.println(title);
String date = (String) JSONEvent.get("Date");
System.out.println(date);
String location = (String) JSONEvent.get("Location");
System.out.println(location);
String description = (String) JSONEvent.get("Description");
System.out.println(description);
String URL = (String) JSONEvent.get("URL");
System.out.println(URL);
Event event = new Event();
event.setName(title);
event.setDate(date);
event.setLocation(location);
event.setDesc(description);
event.setURL(URL);
MainMenu.eventList.add(event);
}
bufferedReader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
}
}
When I run this code, I get the following errors in the console...
Unexpected token END OF FILE at position 0
Does anyone have any idea what this error means?
The very first thing you write to the file is an empty line:
file.write("\n");
So, when reading the file, you're trying to parse an empty string to JSON, hence the exception: the parser finds the end of its input before even having a chance to parse anything.
Instead of relying on the internal format of the generated JSON, and to write several distinct JSON objects to the file, it would be simpler, and safer, to write a single array of objects all at once in the file (replacing its previous content), and to read the whole array at once in memory.
Faced a similar issue. Was trying to write a JSON data record from a file on a Kafka topic. Was getting Unexpected token END OF FILE at position . As a fix, I cleared all the \n characters from the file and tried sending it to the kafka topic. It worked.

URLConnection Reading in as null in java

I'm a building a basic program to query Target's API with a store ID and Product ID which returns the aisle location. I think I'm using the URL constructor incorrectly, however (I've had trouble with it in the past and still don't fully understand them). Below is the code I have, redacted the API Key for obvious reasons. The URL I create is valid when put into a browser and no exceptions are thrown but at the the end when I print out the contents of the page it is null. What am I missing? Any help is really appreciated!
package productVerf;
import java.net.*;
import java.io.*;
public class Verify {
public static void main(String args[]) {
// first input is store id second input is product id
String productID = args[0];
String storeID = args[1];
String file = "/v2/products/storeLocations?productId=" + productID
+ "&storeId=" + storeID
+ "&storeId=694&key=REDACTED";
URL locQuery;
URLConnection lqConection = null;
try {
locQuery = new URL("http", "api.target.com", file);
lqConection = locQuery.openConnection();
} catch (IOException e) {
e.printStackTrace();
}
BufferedReader response;
String responseString = "";
try {
response = new BufferedReader(new InputStreamReader(
lqConection.getInputStream()));
while (response.readLine() != null) {
responseString += response.readLine();
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(responseString);
}
}
Maybe you are reading only even lines
you are reading a line twice? (in while statement...), it looks you reads the first line which is dropped in while condition test. If your response contains only one line, nothing will be readed
use this:
String line;
while ((line=response.readLine()) != null) {
responseString += line;
}

Jsoup library with Android

hay everyone;
I'm having problem displaying image url from java file (Connection), that use Jsoup library to extract the urls and assign them to ArrayList of type String.
public class Connection {
ArrayList<String> StringArray = new ArrayList<String>();
private String fileExtension = "jpg";
private String html = "http://mcs.une.edu.au/~salmutai/cameras";
private int count = 0;
public void UrlExtract() throws Exception {
Document doc = Jsoup.connect(html).get();
Elements castURL = doc.select("a");
for (Element el : castURL) {
String src = el.absUrl("href");
String extension = src.substring(src.lastIndexOf(".") + 1,
src.length());
if (extension.equalsIgnoreCase(fileExtension)) {
StringArray.add(src);
count++;
}
}
}
public int getCount() throws Exception {
return count;
}
public String ImgArray(int i) throws Exception {
String[] StrArray = new String[count];
StrArray = (String[]) StringArray.toArray(StrArray);
return StrArray[i];
}
}
how can I use Toast to show exact url and the count of images.
also, i'm using GridView to display all the images in order.
the pervious code is working in Java Application, but it doesn't work in Android app
Regarding the problem as to why your parsing code doesn't work when running from android, I can only assume that the html retrieved might be different, but that is only a guess. You need to debug the code when running it from you android. A solution might be to output the retrieved html to a log file and see if there is a difference.
Regarding showing your message using Toast:
String text = "Found " + StringArray.size() + " images at the url: " + html;
Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();
NOTE: you don't need to increment the count variable, you can just see how big the StringArray list is, by calling StringArray.size()
the main problem now is when I call this code in Activity 2:
try {
Connection co = new Connection();
co.UrlExtract();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
the app is crashing :(.

Merge two URL in JAVA

I merge two url with the following code.
String strUrl1 = "http://www.domainname.com/path1/2012/04/25/file.php";
String arg = "?page=2";
URL url1;
try {
url1 = new URL(strUrl1);
URL reconUrl1 = new URL(url1,arg);
System.out.println(" url : " + reconUrl1.toString());
} catch (MalformedURLException ex) {
ex.printStackTrace();
}
I'm surprise by the result : http://www.domainname.com/path1/2012/04/25/?page=2
I expect it to be (what browser do) : http://www.domainname.com/path1/2012/04/25/file.php?page=2
Tha javadoc about the constructor URL(URL context, String spec) explain it should respect the RFC.
I'm doing something wrong ?
Thanks
UPDATE :
This is the only problem I encountered with the fonction.
The code already works in all others cases, like browser do
"domain.com/folder/sub" + "/test" -> "domain.com/test"
"domain.com/folder/sub/" + "test" -> "domain.com/folder/sub/test"
"domain.com/folder/sub/" + "../test" -> "domain.com/folder/test"
...
You can always merge the String first and then created the URL based on the merged String.
StringBuffer buf = new StringBuffer();
buf.append(strURL1);
buf.append(arg);
URL url1 = new URL(buf.toString());
try
String k = url1+arg;
URL url1;
try {
url1 = new URL(k);
//URL reconUrl1 = new URL(url1,arg);
System.out.println(" url : " + url1.toString());
} catch (MalformedURLException ex) {
ex.printStackTrace();
}
I haven't read through the RFC, but the context (as mentioned in the Java Doc for URL) is presumably the directory of a URL, which means that the context of
"http://www.domainname.com/path1/2012/04/25/file.php"
is
"http://www.domainname.com/path1/2012/04/25/"
which is why
new URL(url1,arg);
yields
"http://www.domainname.com/path1/2012/04/25/?page=2"
The "workaround" is obviously to concatenate the parts yourself, using +.
you are using the constructor of URL here which takes paramter as URL(URL context, String spec). So you dont pass the php page with the URL but instead with the string. context needs to be the directory. the proper way to do this would be
String strUrl1 = "http://www.domainname.com/path1/2012/04/25";
String arg = "/file.php?page=2";
URL url1;
try {
url1 = new URL(strUrl1);
URL reconUrl1 = new URL(url1,arg);
System.out.println(" url : " + reconUrl1.toString());
} catch (MalformedURLException ex) {
ex.printStackTrace();
}
Try this
String strUrl1 = "http://www.domainname.com/path1/2012/04/25/";
String arg = "file.php?page=2";
URL url1;
try {
url1 = new URL(strUrl1);
URL reconUrl1 = new URL(url1,arg);
System.out.println(" url : " + reconUrl1.toString());
} catch (MalformedURLException ex) {
ex.printStackTrace();
}
When you read the java doc it mentions about the context of the specified URL
Which is the domain and the path:
"http://www.domainname.com" + "/path1/2012/04/25/"
Where "file.php" is considered the text where it belongs to the context mentioned above.
This two parameter overloaded constructor uses the context of a URL as base and adds the second param to create a complete URL, which is not what you need.
So it's better to String add the two parts and then create URL from them:
String contextURL = "http://www.domainname.com/path1/2012/04/25/";
String textURL = "file.php?page=2";
URL url;
try {
url = new URL(contextURL);
URL reconUrl = new URL(url, textURL);
System.out.println(" url : " + reconUrl.toString());
} catch (MalformedURLException murle) {
murle.printStackTrace();
}

Categories

Resources