18
18
# Global variables
19
19
SCRIPT_NAME = 'CW Wizard'
20
20
21
- VERSION = '1.0.4 '
21
+ VERSION = '1.0.5 '
22
22
23
23
EXIT_ERROR_MSG = 'The Wizard encountered issue(s) please check previous logs.\n '
24
24
EXIT_SUCCESS_MSG = 'The Wizard has finish is work, have a great day!\n '
25
25
26
26
# These two variables are extracted and set from the first wantlist url given to the script
27
- CURR_LANG = 'en'
28
27
CURR_GAME = 'Magic'
29
28
30
29
CARDMARKET_TOP_DOMAIN = '.cardmarket.com'
31
30
CARDMARKET_BASE_URL = 'https://www' + CARDMARKET_TOP_DOMAIN
32
31
CARDMARKET_BASE_URL_REGEX = r'^https:\/\/www\.cardmarket\.com'
33
32
34
- # This value can be overwriten via script arguments or via GUI
33
+ # This value can be override via script arguments or via GUI
35
34
MAXIMUM_SELLERS = 20
36
35
36
+ # This value cannot be currently override (this represent a max of 300 offers per card)
37
+ MAXIMUM_NB_REQUESTS_PER_CARD = 6
38
+
37
39
CARD_LANGUAGES = { 'English' : 1 , 'French' : 2 , 'German' : 3 , 'Spanish' : 4 ,
38
40
'Italian' : 5 , 'S-Chinese' : 6 , 'Japanese' : 7 ,
39
41
'Portuguese' : 8 , 'Russian' : 9 , 'Korean' : 10 ,
@@ -229,11 +231,11 @@ def cardmarket_log_in(session, credentials, silently=False):
229
231
230
232
# Step 3: Prepare payload
231
233
token = regex_match .group ('token' )
232
- referal_page_path = '/{} /{}' .format (CURR_LANG , CURR_GAME )
234
+ referal_page_path = '/en /{}' .format (CURR_GAME )
233
235
payload = {'__cmtkn' : token , 'referalPage' : referal_page_path , 'username' : credentials ['login' ], 'userPassword' : credentials ['password' ]}
234
236
235
237
# Step 4: Do the log-in POST request to Cardmarket with the payload
236
- response_post_login = session .post ('{}/{} /{}/PostGetAction/User_Login' .format (CARDMARKET_BASE_URL , CURR_LANG , CURR_GAME ), data = payload )
238
+ response_post_login = session .post ('{}/en /{}/PostGetAction/User_Login' .format (CARDMARKET_BASE_URL , CURR_GAME ), data = payload )
237
239
if response_post_login .status_code != 200 :
238
240
# Issue with the request
239
241
funct_result .addDetailedRequestError ('log-in to Cardmarket' , response_post_login )
@@ -258,7 +260,7 @@ def cardmarket_log_out(session, silently=False):
258
260
if not silently :
259
261
LOG .debug ('------- The Wizard log out of the temporary session on Cardmarket...\n ' )
260
262
261
- response_get_logout = session .get ('{}/{} /{}/PostGetAction/User_Logout' .format (CARDMARKET_BASE_URL , CURR_LANG , CURR_GAME ))
263
+ response_get_logout = session .get ('{}/en /{}/PostGetAction/User_Logout' .format (CARDMARKET_BASE_URL , CURR_GAME ))
262
264
if response_get_logout .status_code != 200 :
263
265
# Issue with the request
264
266
funct_result .addDetailedRequestError ('logout of Cardmarket' , response_get_logout )
@@ -318,6 +320,15 @@ def retrieve_wantlist(session, wantlist_url, continue_on_warning=False):
318
320
319
321
wantlist = None
320
322
323
+ # Get Information from url to recreate it (changing language to english)
324
+ wantlist_url_regex = CARDMARKET_BASE_URL_REGEX + r"\/[a-z]{2}\/(?P<game>\w+)\/Wants/(?P<wantlist_id>\d+)$"
325
+ match = re .match (wantlist_url_regex , wantlist_url )
326
+ if not match :
327
+ funct_result .addError ('The wantlist url ("{}") seems invalid' .format (wantlist_url ))
328
+ return funct_result
329
+
330
+ wantlist_url = '{}/en/{}/Wants/{}' .format (CARDMARKET_BASE_URL , match .group ('game' ), match .group ('wantlist_id' ))
331
+
321
332
# Step 1: Get the desired wantlist page
322
333
response_get_wantlist = session .get (wantlist_url )
323
334
if response_get_wantlist .status_code != 200 :
@@ -409,6 +420,8 @@ def _get_load_more_request_token(load_more_btn):
409
420
410
421
411
422
def load_more_articles (session , funct_result , soup , card , articles_table ):
423
+ nb_of_requests = 0
424
+
412
425
# Step 1: Check if there isn't a load more articles button, in this case we stop
413
426
load_more_btn = soup .find (id = 'loadMoreButton' )
414
427
if not load_more_btn :
@@ -422,7 +435,7 @@ def load_more_articles(session, funct_result, soup, card, articles_table):
422
435
request_token = _get_load_more_request_token (load_more_btn )
423
436
424
437
# Step 3: Retrieve more article until card['maxPrice'] is reached or there is no more article to load
425
- while active :
438
+ while active and nb_of_requests < MAXIMUM_NB_REQUESTS_PER_CARD :
426
439
# Step 3.A: Get the price of the last card currently displayed
427
440
last_article = articles_table .contents [- 1 ]
428
441
last_article_price_str = last_article .find ('div' , class_ = 'price-container' ).find ('span' , class_ = 'text-nowrap' ).contents [0 ]
@@ -433,7 +446,7 @@ def load_more_articles(session, funct_result, soup, card, articles_table):
433
446
# Step 3.B.I: Initialize a payload and do a POST request
434
447
args_base64 = base64 .b64encode (bytes (json .dumps (load_more_args , separators = (',' , ':' )), 'utf-8' ))
435
448
payload = {'args' : request_token + args_base64 .decode ("utf-8" )}
436
- response_post_load_article = session .post ('{}/{} /{}/AjaxAction' .format (CARDMARKET_BASE_URL , CURR_LANG , card_curr_game ), data = payload )
449
+ response_post_load_article = session .post ('{}/en /{}/AjaxAction' .format (CARDMARKET_BASE_URL , card_curr_game ), data = payload )
437
450
if response_post_load_article .status_code != 200 :
438
451
# Issue with the request
439
452
funct_result .addWarning ('Failed to load more articles for card page ("{}")' .format (card ['title' ]))
@@ -442,16 +455,27 @@ def load_more_articles(session, funct_result, soup, card, articles_table):
442
455
443
456
# Step 3.B.II: Handle the request result containing the new articles and the new page_index value
444
457
more_article_soup = BeautifulSoup (response_post_load_article .text , 'html.parser' )
445
- load_more_args ['page' ] = int (more_article_soup .find ('newpage' ).contents [0 ])
458
+ new_page_index_soup = more_article_soup .find ('newpage' )
459
+ if new_page_index_soup :
460
+ load_more_args ['page' ] = int (new_page_index_soup .contents [0 ])
461
+ new_articles_rows_soup = more_article_soup .find ('rows' )
462
+ if new_articles_rows_soup :
463
+ articles_rows_html_str = base64 .b64decode (new_articles_rows_soup .contents [0 ]).decode ("utf-8" )
464
+ articles_table .append (BeautifulSoup (articles_rows_html_str , 'html.parser' ))
465
+ else :
466
+ active = False
446
467
447
- articles_rows_html_str = base64 .b64decode (more_article_soup .find ('rows' ).contents [0 ]).decode ("utf-8" )
448
- articles_table .append (BeautifulSoup (articles_rows_html_str , 'html.parser' ))
449
- if load_more_args ['page' ] < 0 :
450
- # There is no more article available, stop the process
468
+ # TODO: All these if else active = False should be refactored
469
+ if load_more_args ['page' ] < 0 :
470
+ # There is no more article available, stop the process
471
+ active = False
472
+ else :
451
473
active = False
452
474
else :
453
475
active = False
454
476
477
+ nb_of_requests += 1
478
+
455
479
456
480
def populate_sellers_dict (session , sellers , wantlist , articles_comment = False , continue_on_warning = False ):
457
481
funct_result = FunctResult ()
@@ -460,7 +484,7 @@ def populate_sellers_dict(session, sellers, wantlist, articles_comment=False, co
460
484
LOG .debug (' |____ The Wizard is aggregating sellers and articles data for the wantlist ("{}")...' .format (wantlist_url ))
461
485
462
486
for card in wantlist :
463
- # If multiple languages selected with do one request per language
487
+ # If multiple languages selected, do one request per language
464
488
for card_language in card ['languages' ]:
465
489
# Save a sellers list for the current card,
466
490
# to avoid adding multiple time the same article for a seller
@@ -494,7 +518,7 @@ def populate_sellers_dict(session, sellers, wantlist, articles_comment=False, co
494
518
if isinstance (card ['maxPrice' ], Decimal ):
495
519
load_more_articles (session , funct_result , soup , card , articles_table )
496
520
497
- # Step 4: Iterate over articles
521
+ # Step 4: Iterate over articles (a.k.a offers)
498
522
for article_row in articles_table .children :
499
523
# Step 4.A: Check if this is a proper article
500
524
if 'article-row' not in article_row .attrs ['class' ]:
@@ -857,9 +881,7 @@ def check_wantlists_and_max_sellers(wantlist_urls, max_sellers, silently=False):
857
881
# Since new games can be added to Cardmarket, checking "global_game" is not worth it
858
882
859
883
# Step 4: Assign info to global variables
860
- global CURR_LANG
861
884
global CURR_GAME
862
- CURR_LANG = global_language
863
885
CURR_GAME = global_game
864
886
865
887
return funct_result
0 commit comments