@@ -59,33 +59,40 @@ std::vector<cm_market_t> CoinMarketCap::markets(std::string currency_symbol)
5959 toupper (currency_symbol);
6060 auto id = _symbol_to_id.find (currency_symbol);
6161 currency_symbol = id != _symbol_to_id.end () ? id->second : currency_symbol;
62- std::string page =
63- req. getHTML (_reverse_host + " currencies/ " + currency_symbol + " /" );
62+ std::string page = req. getHTML (_reverse_host + " currencies/ " +
63+ currency_symbol + " /markets /" );
6464
6565 CDocument doc;
6666 doc.parse (page.c_str ());
67- CSelection table = doc.find (" #markets-table tbody" );
67+ CSelection table = doc.find (" tbody" );
6868 if (table.nodeNum () == 0 ) {
69- throw std::runtime_error (
70- " Unable to find table with ID markets-table, on " + _reverse_host +
71- " currencies/" + currency_symbol);
69+ throw std::runtime_error (" Unable to find a table on " + _reverse_host +
70+ " currencies/" + currency_symbol + " /markets/" );
7271 }
7372
7473 std::vector<cm_market_t > ret;
7574 CSelection rows = table.nodeAt (0 ).find (" tr" );
7675 auto now =
7776 std::chrono::system_clock::to_time_t (std::chrono::system_clock::now ());
77+
78+ auto _to_number_string = [](std::string text) -> std::string {
79+ text.erase (std::remove (text.begin (), text.end (), ' ,' ), text.end ());
80+ text.erase (std::remove (text.begin (), text.end (), ' $' ), text.end ());
81+ text.erase (std::remove (text.begin (), text.end (), ' ' ), text.end ());
82+ return text;
83+ };
7884 for (size_t i = 0 ; i < rows.nodeNum (); ++i) {
7985 CNode row = rows.nodeAt (i);
8086 CSelection fields = row.find (" td" );
81- if (fields.nodeNum () != 9 ) {
82- throw std::runtime_error (" CMC markets: expected 9 columns, got " +
87+ if (fields.nodeNum () != 10 ) {
88+ throw std::runtime_error (" CMC markets: expected 10 columns, got " +
8389 std::to_string (fields.nodeNum ()));
8490 }
8591
8692 // Skip markets not updated recently
8793 // 8: updated
88- std::string updated_string = fields.nodeAt (8 ).text ();
94+ std::string updated_string =
95+ fields.nodeAt (9 ).find (" div" ).nodeAt (0 ).text ();
8996 at::tolower (updated_string);
9097 if (updated_string != " recently" ) {
9198 continue ;
@@ -101,31 +108,39 @@ std::vector<cm_market_t> CoinMarketCap::markets(std::string currency_symbol)
101108 auto first = pair_string.substr (0 , split_pos);
102109 auto second = pair_string.substr (split_pos + 1 , pair_string.length ());
103110
104- // 3: volumes <span data-usd="value", data-btc="value">
105- CNode span = fields.nodeAt (3 ).find (" span" ).nodeAt (0 );
106- long long int day_volume_usd = std::stoull (span.attribute (" data-usd" ));
107- double day_volume_btc = std::stod (span.attribute (" data-btc" ));
111+ // 3: volumes <div>$1,2,34,5</div>
112+ std::string usd_volume_string =
113+ _to_number_string (fields.nodeAt (3 ).find (" div" ).nodeAt (0 ).text ());
114+
115+ long long int day_volume_usd = std::stoull (usd_volume_string);
116+
117+ // 4: prices <tr>$12,12,12.xx</tr>
118+ std::string price_usd_string =
119+ _to_number_string (fields.nodeAt (4 ).text ());
108120
109- // 4: prices <span data-usd, data-btc
110- span = fields.nodeAt (4 ).find (" span" ).nodeAt (0 );
111- double price_usd = std::stod (span.attribute (" data-usd" ));
112- double price_btc = std::stod (span.attribute (" data-btc" ));
121+ // If there is a * in the string, the price is an outlier
122+ // and we ignore this row.
123+ if (price_usd_string.find (' *' ) != std::string::npos) {
124+ continue ;
125+ }
126+ double price_usd = std::stod (price_usd_string);
113127
114- // 5: xx.yy% percentage
115- std::string percentage_string = fields.nodeAt (5 ).text ();
128+ // 5: xx.yy% percentage <div>a.b%</div>
129+ std::string percentage_string =
130+ fields.nodeAt (5 ).find (" div" ).nodeAt (0 ).text ();
116131 // remove %
117132 percentage_string.pop_back ();
118133 float percent_volume = std::stof (percentage_string);
119134
120- // 6,7: category, feed type unused
135+ // 6 effective liquidity: unused
136+ // 7 category: unused
137+ // 8 fee type unused
121138
122139 cm_market_t market{
123140 .name = name,
124141 .pair = currency_pair_t (first, second),
125142 .day_volume_usd = day_volume_usd,
126- .day_volume_btc = day_volume_btc,
127143 .price_usd = price_usd,
128- .price_btc = price_btc,
129144 .percent_volume = percent_volume,
130145 .last_updated = now,
131146 };
0 commit comments