Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python3
- import urllib.request, urllib.parse, http.cookiejar
- from bs4 import BeautifulSoup
- class piuWrapper():
- # This entire wrapper is built around SQL injections that haven't been patched yet.
- # THIS CAN BREAK AT ANY TIME BY ANDAMIRO IMPROVING SECURITY
- def __init__(self, username, password):
- self.username = username
- self.password = password
- self.cookieJar = http.cookiejar.CookieJar()
- self.opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor())
- def login(self):
- # The website expects usernames to be e-mail addresses.
- url = 'https://[redacted]/piu.login_check.php?'
- credentials = urllib.parse.urlencode({
- 'mb_id' : self.username,
- 'mb_password' : self.password
- })
- self.opener.open(url, credentials.encode())
- # loginSuccess = self.verifyLogin()
- # return loginSuccess
- def scrapeID():
- # Search profile page HTML for profile IDs.
- pass
- url = 'http://[redacted]/piu.mypage/piu.my_profile.php'
- resp = self.opener.open(url)
- html = resp.read().decode('ascii', 'ignore')
- def getScore(self, chartID, primeID):
- resp = self.scrapeScore(chartID, primeID)
- scoreInfo = self.scoreExtract(resp, chartID)
- return scoreInfo
- def scrapeScore(self, chartID, primeID):
- # Takes advantage of a bool blind attack to report individual song/chart play data.
- # Data reported is date of best money score, best money score, and best grade.
- # Best grade is not necessarily tied to best money score Rank Mode is not accounted for.
- url = 'http://[redacted]/piu.item_shop/piu.item_check_window.php?'
- userPlay = urllib.parse.urlencode({
- 'unlock_mode_code_no' : chartID,
- 'this_item_prime_member_no' : primeID
- })
- resp = self.opener.open(url, userPlay.encode())
- return resp
- def scoreExtract(self, resp, chartID):
- # Takes the HTTPResponse and turns it into a readable string.
- # Parses the HTML to locate the table containing song info.
- # Finally returns song title, difficulty, and PR info as an array.
- html = resp.read().decode('ascii', 'ignore')
- soup = BeautifulSoup(html, "html.parser")
- table = soup.find("table", attrs={"class":"step_window_info"})
- scoreInfo = []
- if table == None:
- pass
- else:
- headers = [header.text for header in table.find_all('th')]
- items = [item.text for item in table.find_all('td')]
- #scoreInfo.append(chartID)
- for header in headers:
- if "Lv." not in header:
- continue
- else:
- scoreInfo.append(header)
- for item in items:
- if 'Has no Data' in item:
- scoreInfo.append('Never Played')
- else:
- scoreInfo.append(item)
- return scoreInfo
- # Separate file below
- #############################################################################################################
- import csv, argparse, threading, random, time, os
- from queue import Queue
- from bs4 import BeautifulSoup
- # Local file
- from piuWrapper import piuWrapper
- def main():
- start_time = time.clock
- # Simple arguments for simple programs
- parser = argparse.ArgumentParser()
- parser.add_argument('-u', dest='username', help='Username/E-mail Address (Required)')
- parser.add_argument('-p', dest='password', help='Password (Required)')
- parser.add_argument('-P', dest='primeID', help='Specify your Prime ID (if known).')
- parser.add_argument('-d', dest='dryrun', action='store_true', default='store_false', help='Runs program and simulates fetching data instead of actually fetching data.')
- # parser.add_argument('-P', dest='profile', help='The profile/ID you want to scrape.')
- parser.add_argument('-f', dest='filename', default='Score_Log{0}.csv', help='Specify the output file name.')
- parser.add_argument('-c', dest='chartIDRequest', default=0, help='Request score for specific chart by ID.')
- # parser.add_argument('C', help='Request score for specific chart by name (Not yet functional)')
- args = vars(parser.parse_args())
- username = args['username']
- password = args['password']
- filename = args['filename']
- chartIDRequest = args['chartIDRequest']
- primeID = args['primeID']
- dryrun = args['dryrun']
- chartIDMax = 2565
- threads = 12
- fileInc = 1
- ############################################################
- # if dryrun != True:
- # if chartIDRequest > 0:
- # print(piugame.fakeGetScore(chartIDRequest))
- # else:
- # for chartID in range(chartIDMax + 1):
- # if chartID is not 0:
- # scoreInfo = fakeGetScore(chartID)
- # print(scoreInfo)
- # else:
- # continue
- piugame = piuWrapper(username, password)
- piugame.login()
- # TODO: Verify succesful login.
- allSongInfo = []
- if dryrun == True:
- pass
- else:
- lock = threading.Lock() # threading.Lock() synchronizes console output between threads.
- q = Queue()
- def threadedGetScore(chartID, primeID):
- print('Fetching chart ID {0}\'s score'.format(chartID))
- sleepytime = random.randrange(10, 30)
- time.sleep = sleepytime/100
- songInfo = piugame.getScore(chartID, primeID)
- with lock:
- allSongInfo.append(songInfo)
- # with lock:
- # writer.writerow([songInfo])
- def worker():
- while True:
- queueJob = q.get()
- chartID = queueJob['chartID']
- primeID = queueJob['primeID']
- songInfo = threadedGetScore(chartID, primeID)
- q.task_done()
- #return songInfo
- start = time.perf_counter()
- for chartID in range(chartIDMax):
- queueJob = {'chartID' : chartID, 'primeID' : primeID}
- q.put(queueJob)
- for n in range(threads):
- t = threading.Thread(target=worker)
- t.daemon = True # Thread dies when main thread exits.
- t.start()
- q.join()
- print('Sorting. . .')
- while os.path.exists(filename.format(fileInc)):
- fileInc += 1
- with open(filename.format(fileInc), 'w', newline='') as csvfile:
- allSongInfo.sort()
- writer = csv.writer(csvfile, delimiter=';', quotechar='|')
- writer.writerows(allSongInfo)
- exeTime = (time.clock() - start_time)/60
- print('Execution done in {} minutes'.format())
- input('Done! Step on the center panel to quit.')
- if __name__ == '__main__':
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement