How to get top 400 lists from iTunes - app-store

How do I get the top 400 (or more) lists for apps from iTunes? I need the top paid, free, and grossing lists for each category and overall.
I know the rss feed exists, at https://rss.itunes.apple.com/ but that only gives you the top 200. Yet sites like AppFigures and AppAnnie have lists of the top 400 or 500, and apps in the app store will show you the top 400.
I tried the EPF feed, the popularity table only has twenty rows on it, and from other forums it looks like that feed has been unavailable for months, and it doesn't update as often as these other sites seem to anyway.
I am looking for a solution directly from Apple, not via a third party. I am 99% certain that Apple provides this data hourly, but I do not know the endpoint.

Update 12 October 2015: According to Apple Developer Support as of 9th October 2015 the issue has been resolved.
RSS feeds are indeed currently capped at 200 results (although they have been set to max 400 in the past),
Regarding the EPF relational - some services (e.g. Chomp) have relied on it in the past. I'm not sure about its current status, but if you've tried to use it make sure you get the full weekly release (which size-wise must be in the range of over 5 GBs), not just an increment release. Maybe this is the reason you get just a few rows?
Currently I don't know of other ways to get this information from Apple directly. You may try a free service from f6s or use an API provided by another paid service.
Update - Apple feedback received:
This is an interesting topic for me, so I contacted Apple yesterday and asked them is there any way to retrieve this data directly from them. This morning I received feedback on the availability of chart data from the iTunes Affiliate team at Apple. They confirmed the limitations of the RSS feed and also said the following on the EPF question:
If you are an affiliate, you could look into the EPF Relational to develop your own search results.
The EPF is a multiple-gigabyte download of the complete set of
metadata from the iTunes Store, App Store, and Mac App Store. EPF is
available for affiliates to fully incorporate aspects of the iTunes
and App Store catalogs into a website or app. This tool is only for
tech-savvy affiliates, and knowledge of relational databases setup is
required. Apple will not provide technical support for setting up or
maintaining this tool.
EPF access is only available for approved Affiliate Program
publishers. More information regarding the EPF can be found on the
Enterprise Partner Feed documentation page. Review the documentation
found there, and if you would then like access to the EPF, provide the
following information: ...
Upon further investigation of the ERPF technical documentation I found out that one of the tables in the database contains the top 1000 applications by genre:
So, you should first import the data in your own database, starting from a weekly (multi-gigabyte) release, and then apply any daily (multi-megabyte) updates available since the weekly release. According to Apple the difference between the two is:
Feed Modes
iTunes generates the EPF data in two modes:
full mode
incremental mode
The full export is generated weekly and
contains a complete snapshot of iTunes metadata as of the day of
generation. The incremental export is generated daily and contains
records that have been added or modified since the last full export.
The incremental exports are located relative to the full export on
which they are based.
Provided you've imported the data in a relational database, you should be able to get the needed data with a simple SELECT statement similar to this one:
SELECT application.title, applicationpopularityper_genre.application_rank
FROM applicationpopularityper_genre
JOIN application
ON application.application_id = applicationpopularityper_genre.application_id
WHERE applicationpopularityper_genre.genreid = XX
ORDER BY applicationpopularityper_genre.application_rank ASC;
Regarding hourly updates - by looking at the relational structure, I see that an export_date column is available. You should check if you get multiple dates for each application when executing the select above - if you do, you have data with finer granularity than a day. If not (which is more probable), and this is a dealbreaker for you, you should look at using the services of Appannie and others that I already proposed, that enrich this data with the data they get from developers via itunes connect. If you want the information free, you can try to scrape from Appannie (there are some free tools that do this, but you should know that this may not be very reliable in the long term, so you may be better off paying);
Update 2:
iTunes Affiliate Team confirmed that they are aware of the issue with this table.
Hope this answers your question.

Here's how you do it.... you can hit a URL as follows and supply an iOS5 user agent.
_IOS_DEEP_RANK_URL_BASE = 'https://itunes.apple.com/WebObjects/MZStore.woa/wa/topChartFragmentData?genreId=%s&popId=%s&pageNumbers=%d&pageSize=%d'
_IOS_DEEP_RANK_USERAGENT = 'iTunes-iPad/5.1.1 (64GB; dt:28)'
You need to set the store front too, based on what country you want.
"X-Apple-Store-Front: 143441-1,9"

Would scraping data from AppAnnie be fine?
Used phantomjs and casperjs to scrape top 500 of free, paid and grossing.
Install phantomjs and casperjs in your system
In terminal: casperjs appAnnieTop500Scraper.js
Sample Output
Free Apps
500 apps found:
// not shown: app names in json array format
// json array on file: freeTop500.json
Paid Apps
500 apps found:
// not shown: app names in json array format
// json array on file: paidTop500.json
Grossing Apps
500 apps found:
// not shown: app names in json array format
// json array on file: grossingTop500.json
appAnnieTop500Scraper.js
var free = [];
var paid = [];
var grossing = [];
var FREE_COLUMN_INDEX = 1;
var PAID_COLUMN_INDEX = 2;
var GROSSING_COLUMN_INDEX = 3;
var fs = require('fs');
var casper = require('casper').create();
casper.on("click", function() {
this.echo();
});
casper.on("page.error", function() {
this.echo();
});
function getAppListScraper(columnIndex) {
var selector = document.querySelectorAll('tbody#storestats-top-table tr td:nth-child(' + columnIndex + ') div.item-info div.main-info span.title-info');
return Array.prototype.map.call(selector, function(e) {
return e.getAttribute('title');
});
}
function printToConsole(casper, appList) {
casper.echo(appList.length + ' apps found:');
casper.echo(JSON.stringify(appList));
}
function writeToFile(fileName, content) {
fs.write(fileName, content, 'w');
}
casper.start('https://www.appannie.com/apps/ios/top/?device=iphone', function() {
// click load all button to load 500 apps list
this.click('div#load-more-box span.btn-load p a.load-all');
// wait 5000ms for the apps list to load then scrape it
this.wait(5000, function() {
free = this.evaluate(getAppListScraper, FREE_COLUMN_INDEX);
paid = this.evaluate(getAppListScraper, PAID_COLUMN_INDEX);
grossing = this.evaluate(getAppListScraper, GROSSING_COLUMN_INDEX);
});
});
casper.run(function() {
this.echo('Free Apps');
printToConsole(this, free);
writeToFile("freeTop500.json", JSON.stringify(free));
this.echo('Paid Apps');
printToConsole(this, paid);
writeToFile("paidTop500.json", JSON.stringify(paid));
this.echo('Grossing Apps');
printToConsole(this, grossing);
writeToFile("grossingTop500.json", JSON.stringify(grossing));
this.exit();
});

I know this is an old question, but I recently was faced with the same problem.
After joining the dots from many sites, my solution goes like this:
You will need this list for the genres:
https://affiliate.itunes.apple.com/resources/documentation/genre-mapping/
And this list for the country codes:
https://affiliate.itunes.apple.com/resources/documentation/linking-to-the-itunes-music-store/#Legacy
This link gives you a basic RSS overview and generator, but misses so much:
https://rss.itunes.apple.com/en-us
The next are examples I managed to piece together:
Top 100 Christian & Gospel
https://itunes.apple.com/au/rss/topsongs/genre=22/explicit=true/limit=100/xml
Or, the same one with JSON results
https://itunes.apple.com/au/rss/topsongs/genre=22/explicit=true/limit=100/json
Or, without the explicit songs:
https://itunes.apple.com/au/rss/topsongs/genre=22/limit=100/json
Top 100 CCM
https://itunes.apple.com/au/rss/topalbums/genre=1094/explicit=true/limit=100/xml
Just change the genre id, and the country code.
https://itunes.apple.com/{country code}/rss/topalbums/genre={genre code}/explicit=true/limit=100/xml

Related

Make tile-ID request URL work with mapbox-style "satellite-streets" using folium

I use Python for plotting geospatial data on maps.
For certain map-styles, such as ["basic", "streets", "outdoors", "light", "dark", "satellite", "satellite-streets"], I need a mapbox-access token and for some geospatial plotting packages like folium I even need to create my own link for retrieving the map-tiles.
So far, it worked great with the style "satellite":
mapbox_style = "satellite"
mapbox_access_token = "....blabla"
request_link = f"https://api.mapbox.com/v4/mapbox.{mapbox_style}/{{z}}/{{x}}/{{y}}#2x.jpg90?access_token={mapbox_access_token}"
However, when choosing "satellite-streets" as mapbox-tile-ID, the output doesn't show a background map anymore. It fails with inserting "satellite-streets", "satellitestreets" and "satellite_streets" into the aforementioned link-string.
Why is that and how can I come to know what's the correct tile-ID-name for "satellite-streets"?
I found an answer when reaching out to the customer support.
Apparently, one has to access the static APIs which have specific names listed on their website:
"In general, the styles that you mentioned including
"satellite_streets" that you are referencing are our classic styles
that are going to be deprecated starting June 1st. I would recommend
using our modern static API the equivalent modern styles. This
will allow you to see the most updated street data as well.
Like the example request below:
https://api.mapbox.com/styles/v1/mapbox/satellite-streets-v11/tiles/1/1/0?access_token={your_token}
Here is more info on the deprecation of the classic styles and
the migration guide for them."
My personal adaptation after having tried everything out myself, is:
Via combining the above-mentioned with the details on how to construct a Mapbox-request link on this documention from mapbox' website,
I finally managed to make it work.
An example request looks like so (in python using f-strings):
mapbox_tile_URL = f"https://api.mapbox.com/styles/v1/mapbox/{tileset_ID_str}/tiles/{tilesize_pixels}/{{z}}/{{x}}/{{y}}#2x?access_token={mapbox_access_token}"
The tileset_ID_str could be e.g. "satellite-streets-v11" which can be seen at the following link containing valid static maps.

How can I create a PDF link to the last named version of a Google Document?

I have a live document which is available for download on my website (a manual for a piece of equipment). I want to be able to make changes without these minor changes being visible to the user and so thought that using named versions would be ideal. But I can't see a way to link to the most recent named version.
I'm sure I could use Google Script to create a second document and duplicate into it every time I name the version, but I was thinking there should be an easier way.
The URL I'm currently using is in the following format.
https://docs.google.com/document/d/{Document ID}/export?format=pdf
This works well as long as I don't make changes to the document.
Answer:
Unfortunately, the name of a named version can't be retrieved using the G Suite APIs.
More Information:
The Docs API itself doesn't have methods that allow access to revisions, and while the Drive API does, there isn't a resource representation of the name so the revisions can't be identified by name itself.
Workaround:
If the version you need is the latest version, you can use the Drive API Revisions: list method to retrieve the latest revision and get an export link to that from the exportLinks property of the resource response:
function getExportLink() {
var fileId = "<your-file-id>";
var revisions = Drive.Revisions.list(fileId);
var latestRevision = revisions.items[(revisions.items.length - 1)];
var url = "https://docs.google.com/feeds/download/documents/export/Export?id=";
var revision = "&revision=" + latestRevision.id;
var format = "&exportFormat=pdf";
return url + fileId + revision + format;
}
Note: you have to use the Advanced Drive Service v2 to get Revisions from within Apps Script - to activate this navigate to Resources > Advanced Google Services... and click the switch next to Drive API so that it says on and turns green.
References:
Google Documents API Reference
Download and publish file revisions - Google Drive API
Google Drive API Revisions Overview
Google Drive API Revisions: list method

TYPO3 WEC_Map Extension <script> Tag not inserted in HTML

I’m using Typo3 (Version 6.2.14) and upgraded WEC_Map to version 3.1.3 because I saw a warning on my map which says that I need to use an API key for Google Maps.
So I’ve generated an API key for "Maps Static API" and inserted it in WEC Map Admin. (I’ve used the same key for Browser API Key and Server API Key. Only difference is that I’ve added the secret for the Browser API Key separated by a comma.)
If I’ve visit my FE User Map in the backend the map is showing.
In the frontend instead I get the following error: "
There doesn't seem to be anything to display. Make sure the map is configured correctly and there are users or markers set".
Inspecting the source code I saw that the script tag to maps.googleapis.com is not generated. It looks like this is causing the issue, but I don't know why it is happening.
I hope that someone using a similar setup can point me into the right direction.
Thank you guys. (It would be nice if someone could add the Tag for WEC_Map)
Ok I resolved this. The problem was that I was using the userGroups setting to filter the map markers by multiple user groups.
plugin.tx_wecmap_pi2 {
height = 500
width = 500
showDirections = 1
prefillAddress = 0
initialMapType = G_HYBRID_MAP
controls.mapControlSize = large
controls.showOverviewMap = 1
controls.showMapType = 1
controls.showScale = 1
userGroups = 2,3,5
pid = 2,3,5 # <-- This uses a AND condition
}
Since this setting is using an AND condition under the hood I received the error "There doesn't seem to be anything to display. Make sure the map is configured correctly and there are users or markers set"
In fact I opened a feature request for this 3 years ago. Unfortunately the feature request never made it into the plugin. But Jan Bartels posted a workaround as reply to the feature request. This workaround got lost while updating the extension.
Also recomment to the extension authors to make it more clear in their documentation that the property userGroups uses a AND condition.

Magento Automatically send tracking email

OK, been searching this everywhere, and can't come up with anything... we are externally populating tracking numbers in Magento Community 1.7.0.2 via a sync program from Dydacomp's Mail order Manager software... - it closes the order in Magento and adds a tracking number, but does not trigger the send tracking email function in mage. - I have researched, and seen that there are observers, etc. which appear maybe to be able to do this, but after 20 hours scouring every blog I can find, etc. cannot come up with anything that works!
This link seems to be REALLY in the right direction... but where to put this block of code? I've tried putting it in all kinds of places and none works:
Programmaticly send email when shipping tracking number is set
Any help would be tremendously appreciated.
I developed something similar. I created a module activated by cron (once a day) that checks the last orders that have 'delivered' (complete status).
To run a function in your cron magento module, add to your config.xml
<crontab>
<jobs>
<myModule_myFunction>
<schedule><cron_expr>*/60 * * * *</cron_expr></schedule>
<run><model>emailtracker/cron::myFunction</model></run>
</myModule_myFunction>
</jobs>
</crontab>
For the order to have supplies you can use the following code snippet
$orders = Mage::getModel('sales/order')->getCollection()
->addFieldToFilter('status', 'complete')
->addAttributeToFilter('created_at', array('gteq' => $dataForFilter));
Note that the collection of orders that I created, I make filter by date to avoid retrieving all orders already made​​.
With my collection of recent and complete orders that are possible candidates to receive a tracking email delivery, I can actually work with the orders that are important.
I created a foreach to run in my collection and within that loop, retrieve the tracking number.
foreach($orders as $order) {
$trackings = Mage::getResourceModel('sales/order_shipment_track_collection')
->setOrderFilter($order)
->getData();
for($i=0;$i<count($trackings);$i++) {
$trackingNumber = $trackings[$i]['track_number'];
//Make your php magic here
}
}
From this point, you can work this information the way you want. You can create a function that checks the status of tracking number via API and its delivery service sends an email, or you can imagine.
Important: Remember to check if your magento cron is active.
Note: I did it in Magento 1.6.1.0

Parsing HTML content to use with iPhone app

I don't even know if the title for this question is appropriate, since I'm really lost and need some advice, a starting point to what I need to accomplish.
My iPhone app plays audio streamed from the Internet, with my custom made player. Some links are live streams from Akamai and others are audio files stored on a website. I'm OK with the live streams, but my problem is with the audio files.
As I have many stored audio files that the user can choose from, in different languages, and I don't want to hardcode all of them on my application.Then I need a clever way for the user to browse on the app (pushing the information from the Internet) until he reaches the desired file to play.
The website is organized like this:
First there is list, having all available programs. The user chooses the desired program, then another page shows up and he has to choose a day of the week to play.
My question is: how can I parse this content, with programs and days of the week to choose from? Should I look into HTML parsing? Is there a better/simpler way, like making XML files on the website?
If this helps, the all the webpages end with the .aspx extension.
Please, any advise from a more experienced programmer will greatly help me. Thank you!
I don't think parsing HTML would be the best implementation here. Go for a structured source that doesn't have viewable markup to worry about parsing out or ignoring altogether (also will mean fewer resources thrown at parsing the markup because you will only be parsing what matters).
I'd suggest consuming an XML or JSON source that can be converted to a NSDictionary or other data structure for app use. Here's a neat little class that converts an XML source to an NSDictionary: http://troybrant.net/blog/2010/09/simple-xml-to-nsdictionary-converter/
TBXML is another light-weight XML parser for Objective-C that makes implementing a custom data object up to you: http://www.tbxml.co.uk/
If you'd rather use JSON, there are a number of helpers out there. A good place to start looking would be here: http://cocoaobjects.com/?s=json
If I have understood your question correctly, whatever source you choose, you're likely to want to wind up with a dictionary object that looks something like this:
programs = (
{
program_name: "Foo";
tracks = (
{ day: Monday;
track: audio_file1.mp3;
},
{ day: Tuesday;
track: audio_file2.mp3;
},
{ day: Wednesday;
track: audio_file3.mp3;
}
);
},
{
program_name: "Bar";
tracks = (
{ day: Monday;
track: audio_file4.mp3;
},
{ day: Tuesday;
track: audio_file5.mp3;
},
{ day: Wednesday;
track: audio_file6.mp3;
}
);
},
{
program_name: "Baz";
tracks = (
{ day: Monday;
track: audio_file7.mp3;
},
{ day: Tuesday;
track: audio_file8.mp3;
},
{ day: Wednesday;
track: audio_file9.mp3;
}
);
};
);
Once you've worked out your data source, and converted it to a native data object for working with in Obj-C, you should be able to proceed with coding up a UI that can iterate through the dictionary to provide a list of programs and, in turn, a list of days for each program with accompanying audio files to select to play.
I had a similar need. Consuming data from an ASP.NET site. In the end I used JSON from the .NET side and return JSON. Then, I used the json-framework from Google Code to convert the JSON returned to an NSDictionary. From there the rest is history.
If you are using .NET MVC, then returning JSON results is super simple in a controller. Since you have aspx extensions, I assume that is not the case. There are tons of JSON parsers for C# listed at the bottom of the json.org homepage.
if the website content is static, I would hard code the file names and appropriate URL's to your server within the app and let the user scroll through the list of available items.
if the website content changes, then I would create an XML file on a server which your app downloads on launch (or as you deem fit) and parse within the app, then continue as per static content.
hope this starts you off in the right direction.
Think outside the box: use UIWebView
How about instead of thinking how to parse data and then write UI code to display it we think more of the big picture: we want to present to iPhone user sequence of screens to select and play a recording, and this should be coming from a web server. Only if there was such a tool... but wait, there is! It's called web browser and in the form of UIWebView you can integrate it in your interface, with a little twist.
First, adding UIWebView is very easy, check this http://zpasternack.blogspot.com/2010/09/stupid-uialertview-tricks-part-i.html for illustration.
So let's say we added web view and user can select an audio file from there, what happens then? Turns out you can tell it what should happen, check this question UIWebView open links in Safari . You can hook your code into handling of link clicks and do whatever you please (like hide web view and show player etc).
To give an example, say first in the web view you load
http://foobar.com/somepath/listOfPrograms
which happens to be web page showing list of the programs (which thanks on some clever CSS could look just like an UITableView if you please). User clicks on a programing name, that goes to
http://foobar.com/somepath/programs/CarTalk
which page presents list of weekly shows (again iPhonesque formatted) and when clicked on a link, this now points to
http://audio.foobar.com/somesuch/45678913.mp3
at which point your code recognizes that's audio URL, apprehends control and plays it however it pleases.
How useful is that you may wonder. The answer is "very" :-). It moves the presentation structure away from the app - and to the web server. The app's entry into the UIWebView is the initial URL and the exit is click on audio file link. In a few months someone decides they want the choices not to be made fist programming name and then day of the week; or add additional layer of choice by language or country. No problemo, no need to release new version of the app, just tweak a bit the web pages on the server and the app will pick it up automagically.
It also makes testing the web server side easy - just point any browser to the initial page URL and click-through to see if you make it to a viable audio file. The web master can handle that independently of you, the app writer. You don't even have to care what they use on their side to get those pages, is it hard-coded in html, or comes from a SQL DB, XML tarpit, whatever.
If it were me, and assuming I have some clue as to what you're talking about, I would have a database that shows the relationship between the audio content and the date. Then your spinner for the content would just be updated by a query...
So, for instance, assume a table
+----------------------------------------------------------------------+
| Filename | Language | Date |
+----------------------------------------------------------------------+
| kjslfiewofksalfjslfakj | Swahili | 2011-11-01 |
| shfaahflajfewifhlanfww | Guyanese | 2011-10-08 |
| weijalfjlajfljalsfjewn | French | 2011-11-01 |
| fiwojancanlsjfhkwehwlk | Swahili | 2011-11-01 |
| fhalksflwiehlfnaksflhw | Swahili | 2011-11-03 |
+----------------------------------------------------------------------+
Okay, so if joe schmo reaches the page for the show dated 2011-11-01 and his language is Swahili, two rows will be returned:
+----------------------------------------------------------------------+
| Filename | Language | Date |
+----------------------------------------------------------------------+
| kjslfiewofksalfjslfakj | Swahili | 2011-11-01 |
| fiwojancanlsjfhkwehwlk | Swahili | 2011-11-01 |
+----------------------------------------------------------------------+
You could also easily add references for the date and language that indicate an Akamai record. It doesn't strike me as terribly complicated, but it may mean significant redesign for you. However, you've been purposefully vague on details, so hopefully at least this points you in a right direction.
Edit:
Alright, so after re-reading, there may be a relatively easy way to control content in its organization by using directory structures, but it takes a backseat to my proposed table.
As I understand it, there are potentially three categories at work: program, date, and language.
If I create a file structure (assuming root):
/public_html/audio/[date]/[language]/[program_name].mp4
Then, when the user selects a date and language, we might have:
/public_html/audio/2011-11-14/swahili/the_linux_show.mp4
Then, all we'd have to do is have the $_POST data from the selectors read to provide the show... Unfortunately, this will mean that we have to know the date that the show aired, then language, then show name. This would be a far worse way than a database, but could be done. Use ASP to read directory contents and you can list using loops. Seems pretty simple, but not at all elegant.