install 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. #!/usr/bin/python3
  2. import urllib3
  3. import sys
  4. import os
  5. import requests
  6. import urllib.request
  7. import sqlite3
  8. import wget
  9. """
  10. Toggles.
  11. """
  12. OPT_CREATE_DB = True
  13. OPT_DOWNLOAD = True
  14. OPT_SKILLS = True
  15. OPT_ESSENCES = True
  16. OPT_BASE = True
  17. """
  18. Initializes the database file and creates all the tables.
  19. :param name: The path to the sqlite database.
  20. :returns: Connection to the database.
  21. :raises IntegrityError: The queryes couldn't bre executed.
  22. :raises IOError: The sqlite file couldn't be created.
  23. """
  24. def createDatabase(name):
  25. global OPT_CREATE_DB
  26. print('Configuring database...')
  27. try:
  28. db = sqlite3.connect(name)
  29. if OPT_CREATE_DB == False:
  30. return db
  31. cursor = db.cursor()
  32. cursor.execute('''
  33. CREATE TABLE IF NOT EXISTS monster(
  34. id INTEGER PRIMARY KEY AUTOINCREMENT,
  35. base INTEGER,
  36. stars INT,
  37. element TEXT,
  38. name TEXT,
  39. name_aw TEXT,
  40. type TEXT,
  41. awakeable INT,
  42. img TEXT,
  43. img_aw TEXT
  44. );
  45. ''')
  46. cursor.execute('''
  47. CREATE TABLE IF NOT EXISTS monster_base(
  48. id INTEGER PRIMARY KEY AUTOINCREMENT,
  49. name TEXT
  50. );
  51. ''')
  52. cursor.execute('''
  53. CREATE TABLE IF NOT EXISTS monster_skill(
  54. id INTEGER PRIMARY KEY AUTOINCREMENT,
  55. monster INT,
  56. idx INT,
  57. name TEXT,
  58. desc TEXT,
  59. passive INT,
  60. awaken INT,
  61. upgrade INT,
  62. leader INT,
  63. img TEXT,
  64. cooldown INT
  65. );
  66. ''')
  67. cursor.execute('''
  68. CREATE TABLE IF NOT EXISTS monster_stat(
  69. monster INTEGER,
  70. stars INT,
  71. awake INT,
  72. stat TEXT,
  73. min INT,
  74. max INT
  75. );
  76. ''')
  77. cursor.execute('''
  78. CREATE TABLE IF NOT EXISTS monster_essence(
  79. monster INT,
  80. element TEXT,
  81. grade TEXT,
  82. num INT
  83. );
  84. ''')
  85. cursor.execute('''
  86. CREATE TABLE IF NOT EXISTS monster_location(
  87. monster INT,
  88. location TEXT
  89. );
  90. ''')
  91. cursor.execute('''
  92. CREATE TABLE IF NOT EXISTS monster_collection (
  93. id INTEGER PRIMARY KEY AUTOINCREMENT,
  94. monster INT,
  95. stars INT,
  96. level INT,
  97. awaken INT
  98. );
  99. ''')
  100. db.commit()
  101. cursor.close()
  102. return db
  103. except sqlite3.IntegrityError as e:
  104. print("Error executing statement: " + str(e))
  105. raise
  106. except IOError as e:
  107. print("I/O Error creating database " + name + ": " + str(e))
  108. raise
  109. """
  110. Inserts a row into the database.
  111. :param db: Connection to the database.
  112. :param table: Name of the table to insert into.
  113. :param values: List of values to insert.
  114. :raises IntegrityError: The insert query was unsuccesfull.
  115. """
  116. def insert(db, table, values):
  117. cursor = db.cursor()
  118. placeholders = ''
  119. for x in range(0, len(values)):
  120. placeholders = placeholders + '?, '
  121. placeholders = placeholders[:len(placeholders) - 2]
  122. query = 'INSERT INTO ' + table + ' VALUES (' + placeholders + ')'
  123. try:
  124. cursor.execute(query, values)
  125. except sqlite3.IntegrityError as e:
  126. print('Error Inserting into ' + table + ' with values (' + str(values) + '): ' + str(e))
  127. raise
  128. cursor.close;
  129. def download(url, target):
  130. if OPT_DOWNLOAD == False:
  131. return True
  132. try:
  133. urllib.request.urlretrieve(url, target)
  134. return True
  135. except:
  136. return False
  137. def getDetails(page):
  138. details = []
  139. name = ''
  140. name_aw = ''
  141. img = ''
  142. img_aw = ''
  143. awakeable = 0
  144. mtype = ''
  145. stars = 1
  146. if ('alt="Purple Star"' in page):
  147. if ('alt="Gold Star"' in page):
  148. awakeable = 1 # Awakeable (Gold)
  149. else:
  150. awakeable = 2 # Only awaken (Purple)
  151. else:
  152. awakeable = 0 # No awakeable (Silver)
  153. try:
  154. stars = int(page[page.index('x', page.index('_Star.png"')) + 1:page.index(')', page.index('x', page.index('_Star.png"')))])
  155. except:
  156. stars = 1
  157. pass
  158. header = page[page.index('>') + 1:page.index('<', page.index('>'))]
  159. if ') - ' in header:
  160. name = header[:header.index(' (')]
  161. name_aw = header[header.index(') - ') + 4:]
  162. else:
  163. if ' (' in header:
  164. name = header[:header.index(' (')]
  165. else:
  166. name = header
  167. imgs = page[page.index('<div id="images">'):page.index('</div>', page.index('<div id="images">'))]
  168. if 'data-src="' in imgs:
  169. im = imgs[imgs.index('data-src="') + 10:imgs.index('"', imgs.index('data-src="') + 11)]
  170. imgs = imgs[imgs.index('"', imgs.index('data-src="') + 11):]
  171. else:
  172. im = imgs[imgs.index('<img src="') + 10:imgs.index('"', imgs.index('<img src="') + 11)]
  173. imgs = imgs[imgs.index('"', imgs.index('<img src="') + 11):]
  174. if 'data-src="' in imgs:
  175. img = im
  176. img_aw = imgs[imgs.index('data-src="') + 10:imgs.index('"', imgs.index('data-src="') + 11)]
  177. elif '<img src="' in imgs:
  178. img = im
  179. img_aw = imgs[imgs.index('<img src="') + 10:imgs.index('"', imgs.index('<img src="') + 11)]
  180. else:
  181. img = im
  182. img_aw = ''
  183. if awakeable == 2 and name_aw == '':
  184. name_aw = name
  185. name = ''
  186. if awakeable == 2 and img_aw == '':
  187. img_aw = img
  188. img = ''
  189. mtype = page[page.index('<b>Type:</b>') + 13:page.index('\n', page.index('<b>Type:</b>'))]
  190. details = [name, name_aw, img, img_aw, awakeable, mtype, stars]
  191. return details
  192. def getObtainable(page):
  193. obtainable = []
  194. while 'title=' in page:
  195. obtainable.append(page[page.index('title="') + 7:page.index('"', page.index('title="') + 7)])
  196. page = page[page.index('"', page.index('title="') + 7):]
  197. return obtainable
  198. def getEssences(page):
  199. essences = []
  200. while '\n' in page:
  201. line = page[:page.index('\n')]
  202. if '<span class="essence-number">' in line:
  203. num = line[line.index('<span class="essence-number">') + 29:line.index('</span>', line.index('<span class="essence-number">'))]
  204. desc = line[line.index('alt="') + 5:line.index('"', line.index('alt="') + 6)].split(" ")
  205. elm = desc[2]
  206. if elm == 'Darkness':
  207. elm = 'Dark'
  208. grade = desc[3]
  209. grade = grade[1:len(grade) - 1]
  210. essences.append([num, elm, grade])
  211. page = page[page.index('\n') + 1:]
  212. return essences
  213. def getSkills(page):
  214. skills = []
  215. while '<td style="text-align' in page:
  216. passive = 0
  217. awaken = 0
  218. upgrade = 0
  219. leader = 0
  220. image = ''
  221. name = ''
  222. description = ''
  223. cooldown = 0
  224. name = page[page.index('alt="') + 5:page.index('"', page.index('alt="') + 6)]
  225. if ' (Passive)' in name:
  226. passive = 1
  227. name = name[:name.index(' (Passive)')]
  228. if 'Strengthened ' in name:
  229. upgrade = 1
  230. awaken = 1
  231. name = name[13:]
  232. if len(name) > 12 and name[:13] == 'Leader Skill ':
  233. leader = 1
  234. name = 'LEADER SKILL'
  235. if leader == 1:
  236. subawaken = page[:page.index(':</b> ')]
  237. else:
  238. subawaken = page[:page.index('</b>: ')]
  239. if '(Awakened)' in subawaken:
  240. awaken = 1
  241. image = page[page.index('data-src="') + 10:page.index('"', page.index('data-src="') + 11)]
  242. if leader == 1:
  243. description = page[page.index(':</b> ') + 6:page.index('\n', page.index(':</b> '))]
  244. else:
  245. description = page[page.index('</b>: ') + 6:page.index('\n', page.index('</b>: '))]
  246. if ' (Reusable in ' in description:
  247. try:
  248. cooldown = int(description[description.index(' (Reusable in ') + 14:description.index(' turns)', description.index(' (Reusable in '))])
  249. description = description[:description.index(' (Reusable in ')]
  250. except:
  251. pass
  252. if ' [Automatic Effect]' in description:
  253. description = description[:description.index(' [Automatic Effect]')]
  254. skills.append([name, description, passive, awaken, upgrade, leader, image, cooldown])
  255. page = page[page.index('</tr>', page.index('<td style="text-align')) + 10:]
  256. return skills
  257. def getStats(page, awakeable):
  258. stats = []
  259. ahp = []
  260. aatk = []
  261. adef = []
  262. wahp = []
  263. waatk = []
  264. wadef = []
  265. spd = 0
  266. crir = 0
  267. crid = 0
  268. res = 0
  269. acc = 0
  270. wspd = 0
  271. wcrir = 0
  272. wcrid = 0
  273. wres = 0
  274. wacc = 0
  275. thp = page[page.index('<b>HP</b>'):page.index('</tr>', page.index('<b>HP</b>'))]
  276. while '<td class="monstercell">' in thp:
  277. n = thp[thp.index('<td class="monstercell">') + 24:thp.index('\n', thp.index('<td class="monstercell">'))]
  278. try:
  279. ahp.append(int(thp[thp.index('<td class="monstercell">') + 24:thp.index('\n', thp.index('<td class="monstercell">'))]))
  280. except Exception as e:
  281. pass
  282. thp = thp[thp.index('<td class="monstercell">') + 1:]
  283. tatk = page[page.index('<b>ATK</b>'):page.index('</tr>', page.index('<b>ATK</b>'))]
  284. while '<td class="monstercell">' in tatk:
  285. n = tatk[tatk.index('<td class="monstercell">') + 24:tatk.index('\n', tatk.index('<td class="monstercell">'))]
  286. try:
  287. aatk.append(int(tatk[tatk.index('<td class="monstercell">') + 24:tatk.index('\n', tatk.index('<td class="monstercell">'))]))
  288. except Exception as e:
  289. pass
  290. tatk = tatk[tatk.index('<td class="monstercell">') + 1:]
  291. tdef = page[page.index('<b>ATK</b>'):page.index('</tr>', page.index('<b>ATK</b>'))]
  292. while '<td class="monstercell">' in tdef:
  293. n = tdef[tdef.index('<td class="monstercell">') + 24:tdef.index('\n', tdef.index('<td class="monstercell">'))]
  294. try:
  295. adef.append(int(tdef[tdef.index('<td class="monstercell">') + 24:tdef.index('\n', tdef.index('<td class="monstercell">'))]))
  296. except Exception as e:
  297. pass
  298. tdef = tdef[tdef.index('<td class="monstercell">') + 1:]
  299. # STATS (awakened)
  300. if '#246BB2; width:10%;">Awakened' in page:
  301. mpag = page[page.index('#246BB2; width:10%;">Awakened'):]
  302. thp = page[page.index('<b>HP</b>'):page.index('</tr>', page.index('<b>HP</b>'))]
  303. while '<td class="monstercell">' in thp:
  304. n = thp[thp.index('<td class="monstercell">') + 24:thp.index('\n', thp.index('<td class="monstercell">'))]
  305. try:
  306. wahp.append(int(thp[thp.index('<td class="monstercell">') + 24:thp.index('\n', thp.index('<td class="monstercell">'))]))
  307. except Exception as e:
  308. pass
  309. thp = thp[thp.index('<td class="monstercell">') + 1:]
  310. tatk = page[page.index('<b>ATK</b>'):page.index('</tr>', page.index('<b>ATK</b>'))]
  311. while '<td class="monstercell">' in tatk:
  312. n = tatk[tatk.index('<td class="monstercell">') + 24:tatk.index('\n', tatk.index('<td class="monstercell">'))]
  313. try:
  314. waatk.append(int(tatk[tatk.index('<td class="monstercell">') + 24:tatk.index('\n', tatk.index('<td class="monstercell">'))]))
  315. except Exception as e:
  316. pass
  317. tatk = tatk[tatk.index('<td class="monstercell">') + 1:]
  318. tdef = page[page.index('<b>ATK</b>'):page.index('</tr>', page.index('<b>ATK</b>'))]
  319. while '<td class="monstercell">' in tdef:
  320. n = tdef[tdef.index('<td class="monstercell">') + 24:tdef.index('\n', tdef.index('<td class="monstercell">'))]
  321. try:
  322. wadef.append(int(tdef[tdef.index('<td class="monstercell">') + 24:tdef.index('\n', tdef.index('<td class="monstercell">'))]))
  323. except Exception as e:
  324. pass
  325. tdef = tdef[tdef.index('<td class="monstercell">') + 1:]
  326. mpag = page[page.index('Static Attributes'):]
  327. # STATIC STATS
  328. if awakeable == 1: # For awakeable monsters, skip one line
  329. page = page[page.index('\n', page.index('style="width: 9%;">')):]
  330. spd = page[page.index('style="width: 9%;">') + 19:page.index('\n', page.index('style="width: 9%;">'))]
  331. page = page[page.index('\n', page.index('style="width: 9%;">')):]
  332. crir = page[page.index('style="width: 9%;">') + 19:page.index('\n', page.index('style="width: 9%;">'))]
  333. page = page[page.index('\n', page.index('style="width: 9%;">')):]
  334. crid = page[page.index('style="width: 9%;">') + 19:page.index('\n', page.index('style="width: 9%;">'))]
  335. page = page[page.index('\n', page.index('style="width: 9%;">')):]
  336. res = page[page.index('style="width: 9%;">') + 19:page.index('\n', page.index('style="width: 9%;">'))]
  337. page = page[page.index('\n', page.index('style="width: 9%;">')):]
  338. acc = page[page.index('style="width: 9%;">') + 19:page.index('\n', page.index('style="width: 9%;">'))]
  339. page = page[page.index('\n', page.index('style="width: 9%;">')):]
  340. # Remove percent symbols and cast
  341. spd = int(spd.replace('<b>', '').replace('</b>', ''))
  342. crir = int(crir[:len(crir) - 1].replace('<b>', '').replace('</b>', ''))
  343. crid = int(crid[:len(crid) - 1].replace('<b>', '').replace('</b>', ''))
  344. res = int(res[:len(res) - 1].replace('<b>', '').replace('</b>', ''))
  345. acc = int(acc[:len(acc) - 1].replace('<b>', '').replace('</b>', ''))
  346. # Static stats, awakened
  347. if 'style="width: 9%;"><b>Awakened</b>' in page:
  348. page = page[page.index('style="width: 9%;"><b>Awakened</b>') + 10:]
  349. wspd = page[page.index('style="width: 9%;">') + 19:page.index('\n', page.index('style="width: 9%;">'))]
  350. page = page[page.index('\n', page.index('style="width: 9%;">')):]
  351. wcrir = page[page.index('style="width: 9%;">') + 19:page.index('\n', page.index('style="width: 9%;">'))]
  352. page = page[page.index('\n', page.index('style="width: 9%;">')):]
  353. wcrid = page[page.index('style="width: 9%;">') + 19:page.index('\n', page.index('style="width: 9%;">'))]
  354. page = page[page.index('\n', page.index('style="width: 9%;">')):]
  355. wres = page[page.index('style="width: 9%;">') + 19:page.index('\n', page.index('style="width: 9%;">'))]
  356. page = page[page.index('\n', page.index('style="width: 9%;">')):]
  357. wacc = page[page.index('style="width: 9%;">') + 19:page.index('\n', page.index('style="width: 9%;">'))]
  358. page = page[page.index('\n', page.index('style="width: 9%;">')):]
  359. # Remove percent symbols and cast
  360. wspd = int(wspd.replace('<b>', '').replace('</b>', ''))
  361. wcrir = int(wcrir[:len(wcrir) - 1].replace('<b>', '').replace('</b>', ''))
  362. wcrid = int(wcrid[:len(wcrid) - 1].replace('<b>', '').replace('</b>', ''))
  363. wres = int(wres[:len(wres) - 1].replace('<b>', '').replace('</b>', ''))
  364. wacc = int(wacc[:len(wacc) - 1].replace('<b>', '').replace('</b>', ''))
  365. else:
  366. wspd = None
  367. wcrir = None
  368. wcrid = None
  369. wres = None
  370. wacc = None
  371. stats = [ahp, aatk, adef, wahp, waatk, wadef, spd, crir, crid, res, acc, wspd, wcrir, wcrid, wres, wacc]
  372. return stats
  373. """
  374. Parses the url with info abount one monster, extracts the info and saves it to
  375. the database.
  376. :param db: Connection to the database.
  377. :param url: URL with the info to parse.
  378. :param url: Element of the monster.
  379. :raises Exception: The monster data couldn't be saved.
  380. """
  381. def parseMonster(db, url, element):
  382. http = urllib3.PoolManager()
  383. try:
  384. cursor = db.cursor()
  385. name = '';
  386. name_aw = '';
  387. img = '';
  388. img_aw = '';
  389. awakeable = 0;
  390. mtype = ''
  391. stars = 0
  392. obtainable = []
  393. essences = []
  394. skills = []
  395. ahp = []
  396. aatk = []
  397. adef = []
  398. wahp = []
  399. waatk = []
  400. wadef = []
  401. spd = 0
  402. crir = 0
  403. crid = 0
  404. res = 0
  405. acc = 0
  406. wspd = 0
  407. wcrir = 0
  408. wcrid = 0
  409. wres = 0
  410. wacc = 0
  411. # DEBUG - GOLD
  412. #url = 'http://summonerswar.wikia.com/wiki/Fairy_(Water)_-_Elucia'
  413. # DEBUG - SILVER
  414. #url = 'http://summonerswar.wikia.com/wiki/Forest_Keeper_(Water)'
  415. # DEBUG - PURPLE
  416. #url = 'http://summonerswar.wikia.com/wiki/Rainbowmon'
  417. # DEBUG - Upgradeable skill
  418. #url = 'http://summonerswar.wikia.com/wiki/Paladin_(Wind)_-_Louise'
  419. mpage = http.request('GET', url).data.decode('utf-8');
  420. # Basic details
  421. detailsPage = mpage[mpage.index('<h1 class="page-header__title">'):mpage.index('</tr>', mpage.index('<b>Type:</b>', mpage.index('<h1 class="page-header__title">')))]
  422. details = getDetails(detailsPage)
  423. name = details[0]
  424. name_aw = details[1]
  425. img = details[2]
  426. img_aw = details[3]
  427. awakeable = details[4]
  428. mtype = details[5]
  429. stars = details[6]
  430. # Check if monster already parsed
  431. cursor.execute('SELECT count(id) AS c FROM monster WHERE element = ? AND name = ? AND name_aw = ?', (element, name, name_aw))
  432. if cursor.fetchone()[0] == 0:
  433. # Regions where the monster can be obtained
  434. obtainablePage = mpage[mpage.index('<b>Obtainable from:</b>'):mpage.index('</td>', mpage.index('<b>Obtainable from:</b>'))]
  435. obtainable = getObtainable(obtainablePage)
  436. # Essences required to awaken the monster
  437. if awakeable == 1:
  438. essencesPage = mpage[mpage.index('<div id="essences">'):mpage.index('</table>', mpage.index('<div id="essences">'))]
  439. essences = getEssences(essencesPage)
  440. # Skills
  441. skillsPage = mpage[mpage.index('<table', mpage.index('<table', mpage.index('<div id="skills">') + 1) + 1):mpage.index('</table>', mpage.index('<table', mpage.index('<table', mpage.index('<div id="skills">') + 1) + 1))]
  442. skills = getSkills(skillsPage)
  443. # Stats
  444. statsPage = mpage[mpage.index('Evolution Stats'):]
  445. stats = getStats(statsPage, awakeable)
  446. ahp = stats[0]
  447. aatk = stats[1]
  448. adef = stats[2]
  449. wahp = stats[3]
  450. waatk = stats[4]
  451. wadef = stats[5]
  452. spd = stats[6]
  453. crir = stats[7]
  454. crid = stats[8]
  455. res = stats[9]
  456. acc = stats[10]
  457. wspd = stats[11]
  458. wcrir = stats[12]
  459. wcrid = stats[13]
  460. wres = stats[14]
  461. wacc = stats[15]
  462. # Save monster
  463. strname = element + ' ' + name + " - " + name_aw
  464. if awakeable == 0:
  465. strname = element + ' ' + name
  466. elif awakeable == 2:
  467. strname = name_aw
  468. print (" Saving monster: " + strname + "...")
  469. if img != '':
  470. if download(img, 'public/img/content/monster/' + str(id["monster"]).zfill(3) + '.png'):
  471. img = str(id["monster"]).zfill(3) + '.png'
  472. else:
  473. print("Error downloading image for monster " + str(id["monster"]))
  474. if img != '':
  475. if download(img_aw, 'public/img/content/monster/' + str(id["monster"]).zfill(3) + '_aw.png'):
  476. img_aw = str(id["monster"]).zfill(3) + '_aw.png'
  477. else:
  478. print("Error downloading image for awakened monster " + str(id["monster"]))
  479. insert(db, 'monster', (id["monster"], None, stars, element, name, name_aw, mtype, awakeable, img, img_aw))
  480. # Save locations
  481. for o in obtainable:
  482. insert(db, 'monster_location', (id["monster"], o))
  483. for e in essences:
  484. insert(db, 'monster_essence', (id["monster"], e[1], e[2], e[0]))
  485. # Save skills
  486. idx = 0
  487. for s in skills:
  488. # 0 1 2 3 4 5 6 7
  489. # id monster idx name desc passive awaken upgrade leader img cooldown
  490. if download(s[6], 'public/img/content/skill/' + str(id["monster_skill"]).zfill(4) + '.png'):
  491. s[6] = str(id["monster_skill"]).zfill(4) + '.png'
  492. else:
  493. s[6] = ''
  494. if s[4] == 1:
  495. s[4] = id["monster_skill"] - 1
  496. insert(db, 'monster_skill', (id["monster_skill"], id["monster"], idx, s[0], s[1], s[2], s[3], None, s[5], s[6], s[7]))
  497. idx = idx + 1
  498. id["monster_skill"] = id["monster_skill"] + 1
  499. # Save stats
  500. i = 0
  501. s = stars
  502. while i < len(ahp):
  503. if i + 1 < len(ahp):
  504. insert(db, 'monster_stat', (id["monster"], s, 0, 'HP', ahp[i], ahp[i + 1]))
  505. insert(db, 'monster_stat', (id["monster"], s, 0, 'ATK', aatk[i], aatk[i + 1]))
  506. insert(db, 'monster_stat', (id["monster"], s, 0, 'DEF', aatk[i], aatk[i + 1]))
  507. insert(db, 'monster_stat', (id["monster"], s, 0, 'SPD', spd, spd))
  508. insert(db, 'monster_stat', (id["monster"], s, 0, 'CRIR', crir, crir))
  509. insert(db, 'monster_stat', (id["monster"], s, 0, 'CRID', crid, crid))
  510. insert(db, 'monster_stat', (id["monster"], s, 0, 'RES', res, res))
  511. insert(db, 'monster_stat', (id["monster"], s, 0, 'ACC', acc, acc))
  512. if i + 1 < len(wahp):
  513. insert(db, 'monster_stat', (id["monster"], s, 1, 'HP', wahp[i], wahp[i + 1]))
  514. insert(db, 'monster_stat', (id["monster"], s, 1, 'ATK', waatk[i], waatk[i + 1]))
  515. insert(db, 'monster_stat', (id["monster"], s, 1, 'DEF', waatk[i], waatk[i + 1]))
  516. insert(db, 'monster_stat', (id["monster"], s, 1, 'SPD', wspd, wspd))
  517. insert(db, 'monster_stat', (id["monster"], s, 1, 'CRIR', wcrir, wcrir))
  518. insert(db, 'monster_stat', (id["monster"], s, 1, 'CRID', wcrid, wcrid))
  519. insert(db, 'monster_stat', (id["monster"], s, 1, 'RES', wres, wres))
  520. insert(db, 'monster_stat', (id["monster"], s, 1, 'ACC', wacc, wacc))
  521. s = s + 1
  522. i = i + 2
  523. # Save and proceed
  524. db.commit()
  525. id["monster"] = id["monster"] + 1
  526. except IOError as e:
  527. db.rollback()
  528. print('Error saving monster with id ' + str(id['monster']) + ': ' + str(e))
  529. print(' Current data:')
  530. print(' Name: ' + name)
  531. print(' Name (awaken): ' + name_aw)
  532. print(' Element: ' + element)
  533. print(' Type: ' + mtype)
  534. print(' Awakeable: ' + str(awakeable))
  535. print(' Obtainable:')
  536. for o in obtainable:
  537. print(' ' + o)
  538. print(' Essences:')
  539. for e in essences:
  540. print(' ' + e[0] + ' x ' + e[2] + ' ' + e[1] + ' essences')
  541. print(' Skills:')
  542. for s in skills:
  543. print(' ' + s[1])
  544. pass
  545. #sys.exit("DEBUG EXIT")
  546. def makeDirs():
  547. dirs = ['public/img/content/monster/', 'public/img/content/skill/', 'public/img/content/essence/']
  548. for dir in dirs:
  549. try:
  550. if os.path.isdir(dir) == False:
  551. os.makedirs(dir)
  552. except IOError as e:
  553. print('Unable to create directory: ' + dir);
  554. raise
  555. """
  556. Create the entries for the table monster_base, reading data from the table
  557. monster.
  558. :param db: Connection to the database.
  559. :raise IntegrityError: One or more bases could not be created.
  560. """
  561. def createBases(db):
  562. cursor = db.cursor()
  563. cursor_base = db.cursor()
  564. try:
  565. cursor.execute('SELECT DISTINCT name FROM monster;')
  566. for row in cursor:
  567. try:
  568. cursor_base.execute('INSERT INTO monster_base VALUES (?, ?);', (id["monster_base"], row[0]));
  569. cursor.execute('UPDATE monster SET base = ? WHERE name = ?;', (id["monster_base"], row[0]));
  570. except sqlite3.IntegrityError as e:
  571. print("Error creating monster bases: " + str(e))
  572. raise
  573. id["monster_base"] = id["monster_base"] + 1;
  574. db.commit()
  575. cursor_base.close();
  576. except sqlite3.IntegrityError as e:
  577. print("Error creating monster bases: " + str(e))
  578. raise
  579. """
  580. Downloads the essence icons.
  581. """
  582. def getEssenceIcons():
  583. url = 'http://summonerswar.wikia.com/wiki/Essences'
  584. http = urllib3.PoolManager()
  585. page = http.request('GET', url).data.decode('utf-8')
  586. page = page[page.index('id="List_of_Essences"'):page.index('id="Essence_fusion"')]
  587. while 'data-src="' in page:
  588. name = page[page.index('data-image-name="') + 7:page.index('"', page.index('data-image-name="') + 17)].split(" ")
  589. element = name[2]
  590. if element == 'Darkness':
  591. element = 'Dark'
  592. grade = name[3][1:len(name)]
  593. file = page[page.index('data-src="') + 10:page.index('"', page.index('data-src="') + 11)]
  594. if download(file, 'public/img/content/essence/' + element + '_' + grade + '.png') == False:
  595. print("Unable to save image for essence: " + element + " (" + grade + ")");
  596. page = page[page.index('data-src="') + 10:]
  597. def setBases(db):
  598. cursor = db.cursor()
  599. cursor_base = db.cursor()
  600. cursor.execute('SELECT DISTINCT name FROM monster;')
  601. for row in cursor:
  602. cursor_base.execute('INSERT INTO monster_base VALUES (?, ?);', (id["monster_base"], row[0]));
  603. cursor_base.execute('UPDATE monster SET base = ? WHERE name = ?;', (id["monster_base"], row[0]));
  604. id["monster_base"] = id["monster_base"] + 1;
  605. db.commit()
  606. cursor_base.close();
  607. cursor.close()
  608. """
  609. Starts scrapping th page.
  610. :param db: Connection to the database.
  611. :param baseUrl: URL of the list of monsters of any element, where the element
  612. name has been replaced by '#'.
  613. :param elements: Array with all five elements.
  614. :raise IndexError: The page doesn't match the expected format.
  615. """
  616. def parse(db, baseUrl, elements):
  617. print('Fetching monster data...')
  618. http = urllib3.PoolManager()
  619. makeDirs()
  620. for elm in elements:
  621. url = baseUrl.replace('#', elm)
  622. try:
  623. mlist = http.request('GET', url).data.decode('utf-8')
  624. mlist = mlist[mlist.index('</th></tr>'):]
  625. element = url[url.rfind('/') + 1:url.rfind('_')]
  626. while '</td></tr>' in mlist:
  627. murl = 'http://summonerswar.wikia.com' + mlist[mlist.index('a href="') + 8:mlist.index('"', mlist.index('a href="') + 8)]
  628. parseMonster(db, murl, elm)
  629. mlist = mlist[mlist.index('</td></tr>') + 1:]
  630. except IndexError as e:
  631. print("Error processing " + elm + " monster list page: " + str(e))
  632. print("Maybe the page has changed and this parser is no longer valid.")
  633. raise
  634. #print("ENDED FIRE")
  635. #sys.exit("DEBUG EXIT")
  636. # Detect upgrade skills
  637. cursor = db.cursor()
  638. cursor.execute('UPDATE monster_skill SET upgrade = id + 1 WHERE name = (SELECT name FROM monster_skill s WHERE s.id = monster_skill.id + 1)')
  639. cursor.execute('UPDATE monster_skill SET monster = null WHERE id IN (SELECT upgrade FROM monster_skill);')
  640. cursor.close;
  641. # Get essence icons
  642. getEssenceIcons();
  643. # Create base monsters
  644. setBases(db)
  645. """
  646. Indexes to keep track of the number of insertions in each affected table.
  647. """
  648. id = {}
  649. id["monster"] = 1;
  650. id["monster_base"] = 1;
  651. id["monster_skill"] = 1;
  652. id["monster_essence"] = 1;
  653. id["monster_location"] = 1;
  654. """
  655. Begin script
  656. """
  657. db = createDatabase('application/sw.sqlite')
  658. parse(db, 'http://summonerswar.wikia.com/wiki/#_Monsters', ['Fire', 'Water', 'Wind', 'Light', 'Dark'])
  659. db.close()