Programmatically running advanced eBay search queries - ebay-api

On the E-Bay web site you can search for e. g. bracelets with main color being silver (see screenshot below).
Is it possible to run such query (find newest bracelets with main color silver) programmatically (via the eBay Search API)? If yes - how?
I looked at findItemsAdvanced, but didn't find any reference to color search there.

Refining searches with the Finding API is done through Aspect Filters which are defined in the documentation as:
Aspects are well-known, standardized characteristics of an item. For
example, "Screen Size," "Processor Type," and "Processor Speed" could
be aspects of Laptop PCs. Aspects can vary for different kinds of
items. For example, the aspects of Laptop PCs are different from those
of Women's Dresses (aspects for Women's Dresses might include "Sleeve
Style," "Dress Length," and "Size").
Performing a search is a two step process.
Determine what aspects are available for the category you are searching in.
Choose what aspects you will use and integrate them as filters in your search request.
The following examples use the Finding Kit that eBay provide as part of their Java SDK.
The first example shows how to obtain the aspects that are available. This is achieved via the getHistograms operation. For this example we will use the category Jewelry & Watches > Fashion Jewelry > Rings (67681) that is found on the US eBay site.
import java.util.List;
import com.ebay.services.client.ClientConfig;
import com.ebay.services.client.FindingServiceClientFactory;
import com.ebay.services.finding.*;
public class GetHistograms {
public static void main(String[] args) {
try {
ClientConfig config = new ClientConfig();
config.setApplicationId("<YOUR EBAY APP ID>");
FindingServicePortType serviceClient = FindingServiceClientFactory.getServiceClient(config);
GetHistogramsRequest request = new GetHistogramsRequest();
request.setCategoryId("67681");
GetHistogramsResponse result = serviceClient.getHistograms(request);
AspectHistogramContainer aspectHistogramContainer = result.getAspectHistogramContainer();
List<Aspect> aspects = aspectHistogramContainer.getAspect();
for(Aspect aspect : aspects) {
System.out.println("* " + aspect.getName() + " *");
List<AspectValueHistogram> values = aspect.getValueHistogram();
for(AspectValueHistogram value : values) {
System.out.println(value.getValueName());
}
}
} catch (Exception ex) {
}
}
}
Each category can have multiple aspects that consist of a name, such as Color, and several values such as Red, White, Blue. An example of the output produced by this code is shown below.
Metal Purity
10k
14k
18k
Main Stone
No Stone
Abalone
Agate
Main Color
Aqua
Black
Blue
The names and values returned from getHistograms can now be used as filters in the findItemsAdvanced operation. For the second example we will use the Brand and Main Color aspects. This example also uses the same category as the first.
import java.util.List;
import com.ebay.services.client.ClientConfig;
import com.ebay.services.client.FindingServiceClientFactory;
import com.ebay.services.finding.*;
public class FindItem {
public static void main(String[] args) {
try {
ClientConfig config = new ClientConfig();
config.setApplicationId("<YOUR EBAY APP ID>");
FindingServicePortType serviceClient = FindingServiceClientFactory.getServiceClient(config);
FindItemsAdvancedRequest request = new FindItemsAdvancedRequest();
request.getCategoryId().add("67681");
AspectFilter aspectFilter = new AspectFilter();
aspectFilter.setAspectName("Brand");
aspectFilter.getAspectValueName().add("Paula Abdul");
aspectFilter.getAspectValueName().add("Tiffany");
aspectFilter.getAspectValueName().add("Tommy Hilfiger");
request.getAspectFilter().add(aspectFilter);
aspectFilter = new AspectFilter();
aspectFilter.setAspectName("Main Color");
aspectFilter.getAspectValueName().add("Gold");
aspectFilter.getAspectValueName().add("Silver");
request.getAspectFilter().add(aspectFilter);
PaginationInput pi = new PaginationInput();
pi.setEntriesPerPage(2); request.setPaginationInput(pi);
FindItemsAdvancedResponse result = serviceClient.findItemsAdvanced(request);
System.out.println("Found " + result.getSearchResult().getCount() + " items." );
List<SearchItem> items = result.getSearchResult().getItem();
for(SearchItem item : items) {
System.out.println(item.getTitle());
}
} catch (Exception ex) {
}
}
}

you probably want to use AspectFilters. the input for that can be found in the previous query (as stated in the documentation. see aspectHistogrammContainer)

VariationType appears to be able to do that.

Related

SoftLayer API : getNasNetworkStorage return null

I am checking to get NAS storage list.
I tested 2 ways, one ways is using BAP id, another way is direct account id
first
Using BAP id, get account list.
Using account id, get NAS Storage list.
==> I didn't NAS Storage list
second
Using direct account id, get NAS Storage list
===> successly, get NAS Storage list
I don't Understand difference between ways.
i attached first test code,
"getNasNetworkStorageCount" method returned NAS stroage count, but "getNasNetworkStorage" return "null".
public void test() {
String userId = "IBMxxxxx";
String apiKey = "xxxxx";
client = new RestApiClient().withCredentials(userId, apiKey).withLoggingEnabled();
Account.Service accountService = Account.service(client);
List<Brand> brandList = accountService.getOwnedBrands();
for (Brand brand : brandList) {
Brand.Service brandService = brand.asService(client);
Account.Mask mask = new Account.Mask();
mask.id();
mask.companyName();
mask.accountStatusId();
mask.email();
mask.hardwareCount();
mask.hardware();
mask.virtualGuestCount();
mask.virtualGuests();
mask.nasNetworkStorage();
mask.nasNetworkStorageCount();
brandService.clearMask();
brandService.setMask(mask);
List<Account> accountList = accountList = brandService.getOwnedAccounts();
for (Account account : accountList) {
if(account.getNasNetworkStorageCount() != 0){
System.out.print(account.getNasNetworkStorageCount() + " == ");
System.out.println(account.getNasNetworkStorage().size());
}
}
System.out.println(accountList.size());
}
}
Your results might be those because when you run the SoftLayer_Brand::getOwnedAccounts method it only returns the account for the current user (i.e. the user that’s calling the API)
You can run this Java example and see that effectively the brand retrieves the right account for the user caller, and then all NAS Network Storages that belong to it.
package SoftLayer_Java_Scripts.Examples;
import com.google.gson.Gson;
import com.softlayer.api.*;
import com.softlayer.api.service.Account;
import com.softlayer.api.service.Brand;
import com.softlayer.api.service.network.Storage;
import java.util.List;
public class GetNasNetworkStorage
{
public static void main( String[] args )
{
String user = "set me";
String apiKey = "set me";
long brandId = 2L;
ApiClient client = new RestApiClient().withCredentials(user, apiKey);
Brand.Service brandService = Brand.service(client, brandId);
try
{
List<Account> accountsList = brandService.getOwnedAccounts();
Gson gson = new Gson();
for (Account account : accountsList) {
Account.Service accountService = account.asService(client);
List<Storage> nasStorageList = accountService.getNasNetworkStorage();
for (Storage storage : nasStorageList) {
System.out.println(gson.toJson(storage));
}
}
}
catch(Exception e)
{
System.out.println("Script failed, review the next message for further details: " + e.getMessage());
}
}
}
The difference is that the Brand service is to manage brand accounts whilts using directly the account service is to manage all the information about a particular account.
Currently it may be an issue with the object mask that you are using, however the problem of use the Brand service is that this service was designed only to display the basic information of the all accounts which belong to the brand it was not designed to display all the information of the related accounts (even if you use object masks). I am going to report the issue of the object mask to softlayer, I mean the one related that the nasNetworkStorage returns null, but I already reported similar issues and they were not fix it, because as I told you that is not the propuse of the service.
You also can try setting the object mask as a string maybe that works e.g.
brandService.setMask("mask[id,companyName,accountStatusId,email,hardwareCount,hardware,virtualGuestCount,VirtualGuest,nasNetworkStorage,nasNetworkStorageCount]");
Anyway the most reliable way to get that information of your accounts associated to the brand is using the master user of each accout, I mean using the account service; even the softlayer agent portal uses the master account to get more information of a particular account in your brand.
Let me know if you have more questions
Regards

Can "driver.findElement" be used as method and be called in a program

I am using "driver.findElement" multiple times. So can it be saved in a method and called multiple times?
driver.findElement(By.xpath("//tbody[#id='detailsstockid']/tr/td[12]/a/input")).click();
driver.findElement(By.id("supplier_name")).click();
driver.findElement(By.xpath("//select[#id='supplier_name']/option[7]")).click();
driver.findElement(By.id("catagory_name")).click();
driver.findElement(By.id("productname")).sendKeys("AutoProductNew");
driver.findElement(By.id("productcode")).sendKeys("ap02");
You just need a wrapper like this
public static WebElement findElement(By locator){
WebElement anElement = driver.findElement(locator);
return anElement;
}
findElement(By.id("id")).click();
Basically you can call whatever method available to the object
I think what you are trying to do is to simplify your code... maybe make it more human readable. This is a noble goal but I would suggest that you take a different approach. Without more info, I don't know what your typical script is like. From the example code you provided, I would assume that you are going to a few pages, clicking on things, filling in textboxes, etc. I would suggest that you look into the page object model.
There are a LOT of references on the web on this topic, here's a good one to start with.
http://www.seleniumhq.org/docs/06_test_design_considerations.jsp#page-object-design-pattern
The basic concept is create one Class file per page. [Page doesn't always literally mean an entire page. For example, I would create a separate page object for each popup dialog.] What this allows you to do is to consolidate all the code specific to that page into a single location. If you know what an API is and understand it, you will basically create an API for each page/dialog you touch. If done properly, it will greatly simplify and organize your code and will make creating new scripts drastically easier and they will be much easier to read. The benefits are numerous... one big one is code maintenance is made SO much easier. Imagine you have 100 scripts that all start by logging into the site. Let's assume the design of the login page changes... without the page object model, you will have to update all 100 scripts individually. If you are using the page object model, you open the LoginPage.java class, make the change to the Login() method, and you just fixed all 100 scripts.
You may be asking... how does this answer my question? What it does is turns
driver.findElement(By.id("supplier_name")).click();
into
somePage.clickSupplierName();
in your actual script. I think this is more along the lines of what you are asking without answering your specific question. The .findElement code still exists, but is "hidden away" in the page object.
A simple example. I wrote a script, with supporting page objects, to navigate to Amazon.com, search for Star Wars, return the # of found items, and then navigate to the Today's Deals page. The entire code is below.
program.java (Main script)
public class program
{
public static void main(String[] args)
{
WebDriver driver = new FirefoxDriver();
driver.manage().window().maximize();
driver.get("https://www.amazon.com");
// HOME PAGE
HomePage homepage = new HomePage(driver);
homepage.search("star wars");
// SEARCH RESULTS PAGE
SearchResultsPage searchResultsPage = new SearchResultsPage(driver);
System.out.println(searchResultsPage.getNumberOfResults());
// navigate to the Today's Deals page
searchResultsPage.clickTodaysDealsLink();
// TODAY'S DEALS PAGE
// do more stuff
driver.close();
driver.quit();
System.out.println("Done");
}
}
HomePage.java (Home page page object)
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
public class HomePage
{
WebDriver driver;
private By searchTextboxLocator = By.id("twotabsearchtextbox");
public HomePage(WebDriver driver)
{
this.driver = driver;
}
public void search(String searchString)
{
driver.findElement(searchTextboxLocator).sendKeys(searchString + "\n");
}
}
SearchResultsPage.java (Search results page page object)
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
public class SearchResultsPage
{
WebDriver driver;
private By todaysDealsLinkLocator = By.linkText("Today's Deals");
private By numberOfResultsLocator = By.id("s-result-count");
public SearchResultsPage(WebDriver driver)
{
this.driver = driver;
}
public String getNumberOfResults()
{
// grabs only the total count of search results from the string in the form "1-16 of 7,488,146 results for "
return driver.findElement(numberOfResultsLocator).getText().split(" ")[2];
}
public void clickTodaysDealsLink()
{
driver.findElement(todaysDealsLinkLocator).click();
}
}

Selenium Web Driver : How to map html elements to Java Object.

As part of Selenium Web-driver learning I came across a scenario. Please let me know the professional approach to proceed.
I am testing a eCommerce application where while I click on Mobile link all mobile phones are getting displayed.I want to check whether they are sorted based on name and price. So basically I need to get Name & price of all elements in the result page.
So My Question is there any way I can map html elements to java value objects ? Any API already available for doing this mapping for me ? Something similar to gson api for converting java objects to their corresponding Json representation ?
Deepu Nair
//Get all the mobile phones links into a list before sorting
List<WebElement> mobilelinks=driver.findElements(("locator"));
Map maps = new LinkedHashMap();//use linked hash map as it preserves the insertion order
for(int i=0;i<mobilelinks.size();i++){
//store the name and price as key value pair in map
maps.put("mobilelinks.get(i).getAttribute('name')","mobilelinks.get(i).getAttribute('price')" );
}
/*sort the map based on keys(names) store it in a separate list
sort the map based on values(prices) store it in a separate list
*/
/* Using webdriver click the sort by name and compare it with the list which we got after sorting
and also click sort by prices and compare it with the list*/
To catch an assertion and continue with the test after assertion failures override the Assertion class and create your own CustomAssertion or use SoftAssertions
CustomAssertion.java
public class CustomAssertions extends Assertion {
private Map<AssertionError, IAssert> m_errors = Maps.newLinkedHashMap();
#Override
public void executeAssert(IAssert a) {
try {
a.doAssert();
} catch(AssertionError ex) {
onAssertFailure(a, ex);
System.out.println(a.getActual());
System.out.println(ex.getMessage());
m_errors.put(ex, a);
}
}
public void assertAll() {
if (! m_errors.isEmpty()) {
StringBuilder sb = new StringBuilder("The following asserts failed:\n");
boolean first = true;
for (Map.Entry<AssertionError, IAssert> ae : m_errors.entrySet()) {
if (first) {
first = false;
} else {
sb.append(", ");
}
sb.append(ae.getKey().getMessage());
}
throw new AssertionError(sb.toString());
}
}
}
Instead of using Assertions class to verify the tests use CustomAssertions class
Ex:
//create an object of CustomAssertions class
CustomAssertions custom_assert=new CustomAssertions();
cust_assert.assertTrue(2<1);
cust_assert.assertEquals("test", "testing");
//and finally after finishing the test in aftersuite method call
cust_assert.assertAll();
Hope this helps you if you have any doubts kindly get back...

Tess4J doOCR() for *First Page* of pdf / tif

Is there a way to tell Tess4J to only OCR a certain amount of pages / characters?
I will potentially be working with 200+ page PDF's, but I really only want to OCR the first page, if that!
As far as I understand, the common sample
package net.sourceforge.tess4j.example;
import java.io.File;
import net.sourceforge.tess4j.*;
public class TesseractExample {
public static void main(String[] args) {
File imageFile = new File("eurotext.tif");
Tesseract instance = Tesseract.getInstance(); // JNA Interface Mapping
// Tesseract1 instance = new Tesseract1(); // JNA Direct Mapping
try {
String result = instance.doOCR(imageFile);
System.out.println(result);
} catch (TesseractException e) {
System.err.println(e.getMessage());
}
}
}
Would attempt to OCR the entire, 200+ page into a single String.
For my particular case, that is way more than I need it to do, and I'm worried it could take a very long time if I let it do all 200+ pages and then just substring the first 500 or so.
The library has a PdfUtilities class that can extract certain pages of a PDF.

Simple currency observer

I am trying to use the cryptsy.com's API to get the current price of doge. This is my code.
package main;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import main.Cryptsy.CryptsyException;
import main.Cryptsy.PublicMarket;
public class Main {
public static void main (String [] args) throws CryptsyException, InterruptedException{
Cryptsy cryptsy = new Cryptsy();
while(true){
PublicMarket[] markets = cryptsy.getPublicMarketData();
for(PublicMarket market : markets) {
DecimalFormat df = new DecimalFormat("#.########");
if(market.label.equals("DOGE/BTC"))
System.out.println(new Date() + " " + market.label + " " + df.format(market.lasttradeprice));
}
TimeUnit.SECONDS.sleep(30);
}
}
}
the problem is that the price get updated too rear (30 mins or something) and only if I restart my program. Anyone to know how to get the current price? Also there is connection errors sometimes.
Actually the connection problems are normal with the Cryptsy API. It's slow and often disconnects without an answer. They are overcrowded like all the times.
There is a new API location that should be faster and solve the connection issies, here:
http://pubapi.cryptsy.com/api.php?method=marketdatav2
And also, if you are only interested in one single currency, you can get the market data of only that currency. The whole Answer from Cryptsy for all Currencies is like 300k, so you would waste bandwith, if you poll that every minute or so.
For only one currency it will be like:
http://pubapi.cryptsy.com/api.php?method=singlemarketdata&marketid={MARKET ID}
Where the market ID can be gathered inside the answer of the first URL. But you just need the int ID of the market once, from then on you can always use the direct call..
Every Detail is BTW available here:
https://www.cryptsy.com/pages/api