diff --git a/projects/Comics_Scraper/comicXCD_scraper.py b/projects/Comics_Scraper/comicXCD_scraper.py new file mode 100755 index 00000000..8e85cf42 --- /dev/null +++ b/projects/Comics_Scraper/comicXCD_scraper.py @@ -0,0 +1,123 @@ +#! python3 +import requests, os, bs4, re + +url = 'https://xkcd.com' +#create a directory to store all the comics +os.makedirs('xkcd', exist_ok=True) + + +def imgdownloader(url): + while not url.endswith('#'): + #print out the current page + res = requests.get(url) + res.raise_for_status() #returns None as the request received is 200 which is fine, if received status is 404 there is an exception for bad request + soup = bs4.BeautifulSoup(res.text,"lxml") #r.text is the content of the response in unicode, and r.content is the content of the response in bytes. + #find the comic image on the current page + comic = soup.select('#comic img') #finds tag with comic and its sub tag img + #print(comic) + if comic == []: + #the page did not contaib a comic.. move on + print("No comic was found..") + break + else: + try: + #get the full url to the comic + comicimg = 'http:' + comic[0].get('src') #finds url from the list comic|| basically comic[0] is used as there is just single one element in list!! try print(comic) && print(comic[0]) to see for yourself.. + #check that it is actually a comic and not an interactive page + if "/comics/" in comicimg: + print('Download image %s' % comicimg) + res = requests.get(comicimg) + res.raise_for_status() + #write the image to the xkcd folder + image = open(os.path.join('xkcd', os.path.basename(comicimg)), 'wb') + for chunk in res.iter_content(10000): #default way to write requested content basically chunk is byte by byte writing + image.write(chunk) + image.close() + print('Finished') + break + else: + print("No comic was found..") + break + except requests.exceptions.MissingSchema: + print("Error in downloading img!!") + break + + +def getLatestComicNumber(url): + res=requests.get(url) + res.raise_for_status() #returns None as the request received is 200 which is fine, if received status is 404 there is an exception for bad request + soup=bs4.BeautifulSoup(res.text,"lxml") + prevLink=soup.select('a[rel="prev"]')[0] + url = 'https://xkcd.com' + prevLink.get('href') + x=re.findall('\d+',url) + x=int(x[0])+1 + #print(x) + return x; + + +#this function is basically traversing backwards, it starts from the most recent comic and goes back until n-1 n being number of pages +#as there are no prev before 1 ( :p quite obvious) +def getNextComic(soup): + prevLink=soup.select('a[rel="prev"]')[0] + url = 'https://xkcd.com' + prevLink.get('href') # gets /comic-num/ from current page prev button ..basic crawling!! + return url; + +def getSpecificComic(comic_number): #comic_number + res=url+'/'+comic_number+'/' + try: + imgdownloader(res) + except Exception as e: + print(str(e)) + + +def batchDownloader(): + url = 'https://xkcd.com' + #check to make sure it's not the first page + while not url.endswith('#'): + #print out the current page + print('Current page: %s' % url) + res = requests.get(url) + res.raise_for_status() #returns None as the request received is 200 which is fine, if received status is 400 + soup = bs4.BeautifulSoup(res.text,"lxml") #r.text is the content of the response in unicode, and r.content is the content of the response in bytes. + #find the comic image on the current page + comic = soup.select('#comic img') #finds tag with comic and its sub tag img + #print(comic) + if comic == []: + #the page did not contaib a comic.. move on + print("No comic was found..") + else: + try: + #get the full url to the comic + comicimg = 'http:' + comic[0].get('src') #finds url from the list comic|| basically comic[0] is used as there is just single one element in list!! try print(comic) && print(comic[0]) to see for yourself.. + #check that it is actually a comic and not an interactive page + if "/comics/" in comicimg: + print('Download image %s' % comicimg) + res = requests.get(comicimg) + res.raise_for_status() + #write the image to the xkcd folder + image = open(os.path.join('xkcd', os.path.basename(comicimg)), 'wb') + for chunk in res.iter_content(10000): #default way to write requested content basically chunk is byte by byte writing + image.write(chunk) + image.close() + else: + print("No comic was found..") + except requests.exceptions.MissingSchema: + url = getNextComic(soup) + continue + url=getNextComic(soup) #basically for downloading the first image + #all comics have downloaded + print('Finished') + +def main(): + x=int(input("Choose your option: \n1.Download all images\t2.Download Specific image\n")) + if x==1: + batchDownloader() + if x==2: + y=str(input("Enter any comic number between 1-"+str(getLatestComicNumber(url)))) + try: + getSpecificComic(y) + except Exception as e: + print(str(e)) + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/projects/Comics_Scraper/requirements.txt b/projects/Comics_Scraper/requirements.txt new file mode 100644 index 00000000..588cb5da --- /dev/null +++ b/projects/Comics_Scraper/requirements.txt @@ -0,0 +1 @@ +bs4 \ No newline at end of file diff --git a/projects/Text_to_SpreadSheet/requirements.txt b/projects/Text_to_SpreadSheet/requirements.txt new file mode 100644 index 00000000..a717bf13 --- /dev/null +++ b/projects/Text_to_SpreadSheet/requirements.txt @@ -0,0 +1 @@ +openpyxl \ No newline at end of file diff --git a/projects/Text_to_SpreadSheet/text1.txt b/projects/Text_to_SpreadSheet/text1.txt new file mode 100755 index 00000000..9ebd8106 --- /dev/null +++ b/projects/Text_to_SpreadSheet/text1.txt @@ -0,0 +1,5 @@ +text1 +tex1, 1 +tex1, 2 +text1, 3 +text1, 4 \ No newline at end of file diff --git a/projects/Text_to_SpreadSheet/text2.txt b/projects/Text_to_SpreadSheet/text2.txt new file mode 100755 index 00000000..d7abc9a3 --- /dev/null +++ b/projects/Text_to_SpreadSheet/text2.txt @@ -0,0 +1,5 @@ +text2 +text2, 1 +text2, 2 +text2, 3 +text2, 4 \ No newline at end of file diff --git a/projects/Text_to_SpreadSheet/text3.txt b/projects/Text_to_SpreadSheet/text3.txt new file mode 100755 index 00000000..fd58e36f --- /dev/null +++ b/projects/Text_to_SpreadSheet/text3.txt @@ -0,0 +1,5 @@ +text3 +text3, 1 +text3, 2 +text3, 3 +text3, 4 \ No newline at end of file diff --git a/projects/Text_to_SpreadSheet/textToSheet.py b/projects/Text_to_SpreadSheet/textToSheet.py new file mode 100755 index 00000000..1914ae13 --- /dev/null +++ b/projects/Text_to_SpreadSheet/textToSheet.py @@ -0,0 +1,32 @@ +import os +import openpyxl + + +def textToSheet(directory, filename): + """converts text files to columns in excel worksheet + Args: + directory (str): folder containing text files + filename (str): name of excel file + Returns: + None + """ + wb = openpyxl.Workbook() + wb.create_sheet(index=0, title='result') + sheet = wb.active + + colIndex = 1 + + # write text files as columns in worksheet + for file in os.listdir(): + if file.endswith('.txt'): + rowIndex = 1 + with open(file) as f: + for line in f: + sheet.cell(row=rowIndex, column=colIndex).value = line + rowIndex += 1 + colIndex += 1 + + wb.save(filename) + +if __name__ == "__main__": + textToSheet('.', 'text-to-cols.xlsx') \ No newline at end of file diff --git a/projects/Worksheet_to_text/requirements.txt b/projects/Worksheet_to_text/requirements.txt new file mode 100644 index 00000000..a717bf13 --- /dev/null +++ b/projects/Worksheet_to_text/requirements.txt @@ -0,0 +1 @@ +openpyxl \ No newline at end of file diff --git a/projects/Worksheet_to_text/sheetToTextFile.py b/projects/Worksheet_to_text/sheetToTextFile.py new file mode 100755 index 00000000..b13aedcc --- /dev/null +++ b/projects/Worksheet_to_text/sheetToTextFile.py @@ -0,0 +1,26 @@ +import os +import openpyxl + + +def toTextFiles(filename): + """writes column data in worksheet into text files + Args: + filename (str): name of worksheet to read from + Returns: + None + """ + wb = openpyxl.load_workbook(filename) + sheet = wb.active + count = 1 + + for colObj in sheet.columns: + + with open('text-'+str(count)+'.txt', 'w') as file: + for cellObj in colObj: + file.write(cellObj.value) + + count += 1 + + +if __name__ == "__main__": + toTextFiles('worksheet.xlsx') \ No newline at end of file diff --git a/projects/Worksheet_to_text/worksheet.xlsx b/projects/Worksheet_to_text/worksheet.xlsx new file mode 100755 index 00000000..78a4dd30 Binary files /dev/null and b/projects/Worksheet_to_text/worksheet.xlsx differ diff --git a/projects/chore-assignment-emailer/chore-emailer.py b/projects/chore-assignment-emailer/chore-emailer.py new file mode 100755 index 00000000..99d86a2d --- /dev/null +++ b/projects/chore-assignment-emailer/chore-emailer.py @@ -0,0 +1,61 @@ +import random +import smtplib + +def emailer(chores, emails): + """emails random chores to emails + Args: + chores: list of chores + emails: list of emails to send chores + Returns: + None + """ + if not emails: + print('emails list should not be empty') + return + + if not chores: + print('chores list should not be empty') + return + + chores_dict = {} + + f = 0 # front of emails list + + while chores: + + randomChore = random.choice(chores) + chores.remove(randomChore) + email = emails[f] + chores_dict.setdefault(email, []) + chores_dict[email].append(randomChore) + + f = (f+1) % len(emails) # use list circularly + + smtpObj = smtplib.SMTP('smtp.gmail.com', 587) + smtpObj.ehlo() + + + email = input('Enter your email: ') + password = input('Enter your email password: ') + + smtpObj.starttls() + smtpObj.login(email, password) + # See https://support.google.com/accounts/answer/6010255 if (Bad Credentials Error) + + for k, v in chores_dict.items(): + c = ', '.join(v) + print('Sending email to %s...' % k) + sendmailStatus = smtpObj.sendmail(email, k, \ + 'Subject: Your Chores.\nHi There!, {} are your chores'.format(c)) + if sendmailStatus != {}: + print('There was a problem sending email to %s: %s' % (email, + sendmailStatus)) + + smtpObj.quit() + + + + + +if __name__ == "__main__": + emailer(['dishes', 'bathroom', 'vacuum', 'walk dog'], ['example@yahoo.com, example2@yahoo.com']) \ No newline at end of file diff --git a/projects/comma-code/comma-code.py b/projects/comma-code/comma-code.py new file mode 100755 index 00000000..22b3a4a0 --- /dev/null +++ b/projects/comma-code/comma-code.py @@ -0,0 +1,21 @@ +def comma_code(items): + """ Combines list into a string of the form item1, item2, and item 3 + Args: + items (list): List of strings + + Returns: + string: list items combined into a string + """ + item_len = len(items) + + if item_len == 0: + return '' + elif item_len == 1: + return items[0] + + return ', '.join(items[:-1]) + ', and ' + items[-1] + + +if __name__ == "__main__": + spam = ['apples', 'bananas', 'tofu', 'cats'] + print(comma_code(spam)) \ No newline at end of file diff --git a/projects/custom-invitations/customInvitations.py b/projects/custom-invitations/customInvitations.py new file mode 100755 index 00000000..17ecc627 --- /dev/null +++ b/projects/custom-invitations/customInvitations.py @@ -0,0 +1,64 @@ +import os + + +import docx +from docx.enum.text import WD_ALIGN_PARAGRAPH +from docx.shared import Pt + + +def createInvitations(txtFile, docName): + """Creates invitations based on names in txt file + Args: + txtFile (str): text file to read from + docName (str): doc file to save invitations in + """ + doc = docx.Document() + + intro = 'It would be a pleasure to have the company of' + address = 'at 11101 Memory lane on the evening of' + date = 'April 31st' + time = "at 24 O'Clock" + + with open(txtFile) as guestList: + for guest in guestList: + name = guest[:-1] + p1 = doc.add_paragraph() + p1.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER + f1 = p1.add_run(intro) + f1.font.bold = True + f1.font.italic = True + f1.font.size = Pt(13) + + p2 = doc.add_paragraph() + p2.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER + f2 = p2.add_run(name) + f2.font.bold = True + f2.font.size = Pt(15) + + p3 = doc.add_paragraph() + p3.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER + f3 = p3.add_run(address) + f3.font.bold = True + f3.font.italic = True + f3.font.size = Pt(12) + + p4 = doc.add_paragraph() + p4.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER + f4 = p4.add_run(date) + f4.font.size = Pt(12) + + p5 = doc.add_paragraph() + p5.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER + f5 = p5.add_run(time) + f5.font.bold = True + f5.font.italic = True + f5.font.size = Pt(12) + + doc.add_page_break() + + doc.save(docName) + + + +if __name__ == "__main__": + createInvitations('guests.txt', 'invitations.docx') \ No newline at end of file diff --git a/projects/custom-invitations/guests.txt b/projects/custom-invitations/guests.txt new file mode 100755 index 00000000..e7f09c79 --- /dev/null +++ b/projects/custom-invitations/guests.txt @@ -0,0 +1,5 @@ +Prof. Plum +Miss Scarlet +Col. Mustard +Al Sweigart +Robocop \ No newline at end of file diff --git a/projects/custom-invitations/requirements.txt b/projects/custom-invitations/requirements.txt new file mode 100644 index 00000000..7a6646fe --- /dev/null +++ b/projects/custom-invitations/requirements.txt @@ -0,0 +1 @@ +docx \ No newline at end of file diff --git a/projects/custom-seating-cards/Pacifico.ttf b/projects/custom-seating-cards/Pacifico.ttf new file mode 100755 index 00000000..6d47cdc9 Binary files /dev/null and b/projects/custom-seating-cards/Pacifico.ttf differ diff --git a/projects/custom-seating-cards/custom_cards.py b/projects/custom-seating-cards/custom_cards.py new file mode 100755 index 00000000..46a422bd --- /dev/null +++ b/projects/custom-seating-cards/custom_cards.py @@ -0,0 +1,44 @@ +import os + + +from PIL import Image, ImageDraw, ImageFont + +def make_cards(guestList): + """Makes custom cards for each guest + Args: + guestList (str): Path to file containing guest list + Returns: + None + """ + # make folder to store resulting images + os.makedirs('imageCards', exist_ok=True) + + # load flower image + flowerImg = Image.open('flower.png') + + # read each guest from file + with open(guestList) as file: + for line in file: + guest = line[:-1] + + # create image + card = Image.new('RGBA', (288, 360), 'white') + # add flower image + card.paste(flowerImg, (0, 0)) + + # create border around image + border = Image.new('RGBA', (291, 363), 'black') + border.paste(card, (3,3)) + + # draw guest name + draw_obj = ImageDraw.Draw(border) + card_font = ImageFont.truetype('Pacifico.ttf', 24) + draw_obj.text((120, 100), guest, fill='red', font=card_font) + + # save resulting image + imageName = '{}_card.png'.format(guest) + border.save(os.path.join('imageCards', imageName)) + + +if __name__ == "__main__": + make_cards('guests.txt') \ No newline at end of file diff --git a/projects/custom-seating-cards/flower.png b/projects/custom-seating-cards/flower.png new file mode 100755 index 00000000..2db93dfc Binary files /dev/null and b/projects/custom-seating-cards/flower.png differ diff --git a/projects/custom-seating-cards/guests.txt b/projects/custom-seating-cards/guests.txt new file mode 100755 index 00000000..e7f09c79 --- /dev/null +++ b/projects/custom-seating-cards/guests.txt @@ -0,0 +1,5 @@ +Prof. Plum +Miss Scarlet +Col. Mustard +Al Sweigart +Robocop \ No newline at end of file diff --git a/projects/custom-seating-cards/requirements.txt b/projects/custom-seating-cards/requirements.txt new file mode 100644 index 00000000..5873a222 --- /dev/null +++ b/projects/custom-seating-cards/requirements.txt @@ -0,0 +1 @@ +Pillow \ No newline at end of file diff --git a/projects/excel-to-csv-converter/excelToCsv.py b/projects/excel-to-csv-converter/excelToCsv.py new file mode 100755 index 00000000..7abb45d8 --- /dev/null +++ b/projects/excel-to-csv-converter/excelToCsv.py @@ -0,0 +1,45 @@ +import os +import csv + + +import openpyxl + + +def excelToCsv(folder): + """converts sheets in every excel file in a folder to csv + Args: + folder (str): folder containing excel files + Returns: + None + """ + for excelFile in os.listdir(folder): + # Skip non-xlsx files, load the workbook object. + if not excelFile.endswith('xlsx'): + continue + wb = openpyxl.load_workbook(excelFile) + + for sheetName in wb.get_sheet_names(): + # Loop through every sheet in the workbook. + sheet = wb.get_sheet_by_name(sheetName) + + # Create the CSV filename from the Excel filename and sheet title. + csvFilename = excelFile.split('.')[0]+'_'+sheet.title+'.csv' + csvFileObj = open(csvFilename, 'w', newline='') + + # Create the csv.writer object for this CSV file. + csvWriter = csv.writer(csvFileObj) + + # Loop through every row in the sheet. + for rowObj in sheet.rows: + rowData = [] # append each cell to this list + # Loop through each cell in the row. + for cellObj in rowObj: + # Append each cell's data to rowData. + rowData.append(cellObj.value) + # Write the rowData list to the CSV file. + csvWriter.writerow(rowData) + + csvFileObj.close() + +if __name__ == "__main__": + excelToCsv('.') \ No newline at end of file diff --git a/projects/excel-to-csv-converter/requirements.txt b/projects/excel-to-csv-converter/requirements.txt new file mode 100644 index 00000000..a717bf13 --- /dev/null +++ b/projects/excel-to-csv-converter/requirements.txt @@ -0,0 +1 @@ +openpyxl \ No newline at end of file diff --git a/projects/fantasy-game-inventory/game-inventory.py b/projects/fantasy-game-inventory/game-inventory.py new file mode 100755 index 00000000..afc94017 --- /dev/null +++ b/projects/fantasy-game-inventory/game-inventory.py @@ -0,0 +1,46 @@ +def displayInventory(inventory): + """ Displays how much of what a player has in inventory + + Args: + inventory (dict): Inventory containing items and their counts + + Returns: + None + """ + print("Inventory:") + item_total = 0 + + for k, v in inventory.items(): + print(v, ' ', k) + item_total += v + + print("Total number of items: " + str(item_total)) + +def addToInventory(inventory, addedItems): + """ Add Items to inventory + Args: + inventory (dict): Inventory containing items and their counts + addedItems (list): Items to add to inventory + + Returns: + updatedInventory (dict): Inventory containing updated items and their counts + """ + updatedInventory = dict(inventory) + # your code goes here + for item in addedItems: + updatedInventory.setdefault(item, 0) + updatedInventory[item] += 1 + + return updatedInventory + + + +if __name__ == "__main__": + + stuff = {'rope': 1, 'torch': 6, 'gold coin': 42, 'dagger': 1, 'arrow': 12} + displayInventory(stuff) + + inv = {'gold coin': 42, 'rope': 1} + dragonLoot = ['gold coin', 'dagger', 'gold coin', 'gold coin', 'ruby'] + inv = addToInventory(inv, dragonLoot) + displayInventory(inv) \ No newline at end of file diff --git a/projects/fill-gaps/fill_gaps.py b/projects/fill-gaps/fill_gaps.py new file mode 100755 index 00000000..203b9a64 --- /dev/null +++ b/projects/fill-gaps/fill_gaps.py @@ -0,0 +1,88 @@ +import os +import re +import shutil + +def getFilesWithPrefix(folderPath, prefix): + """get all files with a certain prefix + Args: + folderPath (str): path to folder to search + Returns: + + """ + fileRegex = re.compile(prefix+'(\d{1,})(.\w+)') + fileList = sorted( [file for file in os.listdir(folderPath) if fileRegex.match(file)] ) + return fileList + +def fillGaps(folderPath, prefix): + """fill gaps in numbering of files in folder + Args: + folderPath (str): path to folder to search + prefix (str): prefix of files to fill gap + Returns: + None + """ + fileList = getFilesWithPrefix(folderPath, prefix) # files sorted ascending order + fileRegex = re.compile(prefix+'(\d{1,})(.\w+)') + + start = int(fileRegex.search(fileList[0]).group(1)) # start with the minimum number in list + count = start # count to be incremented during checks for gaps + max_length = len(fileRegex.search(fileList[-1]).group(1)) # max length of largest number, for padding zeros + + for file in fileList: + + mo = fileRegex.search(file) + fileNum = int(mo.group(1)) + + if fileNum != count: + newFileName = prefix + '0'*(max_length-len(str(fileNum))) + str(count) + mo.group(2) + shutil.move(os.path.abspath(file), os.path.abspath(newFileName)) + + count += 1 + +def insertGaps(folderPath, prefix, index): + """insert gaps in numbering of files in folder + Args: + folderPath (str): path to folder to search + prefix (str): prefix of files to insert gap + index (int): where to insert the gap + Returns: + None + """ + + fileList = getFilesWithPrefix(folderPath, prefix) # files sorted ascending order + fileRegex = re.compile(prefix+'(\d{1,})(.\w+)') + + max_length = len(fileRegex.search(fileList[-1]).group(1)) # max length of largest number, for padding zeros + + firstIndex = int(fileRegex.search(fileList[0]).group(1)) # smallest number + lastIndex = int(fileRegex.search(fileList[-1]).group(1)) # largest number + + if index >= firstIndex and index <= lastIndex: # if gap index falls in range + + i = 0 + currIndex = firstIndex + while currIndex < index: + # loop till the file number is >= gap index + i += 1 + currIndex = int(fileRegex.search(fileList[i]).group(1)) + + if currIndex == index: # if gap index is taken, make a gap else already free + + for file in fileList[i:][::-1]: + # loop through reversed file list, to prevent overwriting results and increment file number + + mo = fileRegex.search(file) + newFileNum = int(mo.group(1)) + 1 + newFileName = prefix + '0'*(max_length-len(str(newFileNum))) + str(newFileNum) + mo.group(2) + shutil.move(os.path.abspath(file), os.path.abspath(newFileName)) + + +if __name__ == "__main__": + + with open('spam001.txt', 'w') as s1, open('spam003.txt', 'w') as s3: + s1.write('spam001') + s3.write('spam003') + + fillGaps('.', 'spam') + #insertGaps('.', 'spam', 2) + \ No newline at end of file diff --git a/projects/find-unneeded-files/find_unneeded.py b/projects/find-unneeded-files/find_unneeded.py new file mode 100755 index 00000000..cf02fe96 --- /dev/null +++ b/projects/find-unneeded-files/find_unneeded.py @@ -0,0 +1,44 @@ +import os + +def findUnneeded(folderPath, rejectSize): + """walks through a folder tree and searches for exceptionally large files or folders + Args: + folderPath (str): path of folder to walk + rejectSize (int): file size in bytes to possibly delete + Returns: + None + """ + root = os.path.abspath(folderPath) + + for doc in os.listdir(root): + + docPath = os.path.join(root, doc) + + if os.path.isdir(docPath): + size = getDirSize(docPath) + else: + size = os.path.getsize(docPath) + + if size > rejectSize: + print(f'{docPath}: {size}') + +def getDirSize(start_path): + """Finds the total size of a folder and it's contents + Args: + start_path (str): path to folder + Returns: + size (int): folder size in bytes + """ + size = 0 + + for folderName, subFolder, filename in os.walk(start_path): + for file in filename: + filePath = os.path.join(folderName, file) + size += os.path.getsize(filePath) + + + return size + + +if __name__ == '__main__': + findUnneeded('..', 1000) \ No newline at end of file diff --git a/projects/image-site-downloader/imgur-downloader.py b/projects/image-site-downloader/imgur-downloader.py new file mode 100755 index 00000000..66edf485 --- /dev/null +++ b/projects/image-site-downloader/imgur-downloader.py @@ -0,0 +1,61 @@ +import os +import requests +import bs4 + +def downloader(query, max_save, output_path): + """ + Args: + query (str): search query + max_save (int): max number of images to save to results + Returns: + None + """ + + # create imgur search url + searchUrl = 'https://imgur.com/search' + queryUrl = searchUrl+'?q='+query + + # set up output_path + abs_output_path = os.path.abspath(output_path) + os.makedirs(abs_output_path, exist_ok=True) + + # Make request to imgur with query + res1 = requests.get(queryUrl) + + try: + res1.raise_for_status() + + # parse res.text with bs4 to images + imugurSoup = bs4.BeautifulSoup(res1.text, 'html.parser') + images = imugurSoup.select('.image-list-link img') + + # extract number image urls + num_to_save = min(max_save, len(images)) + download_links = ['https:'+img.get('src') for img in images[:num_to_save]] + + # make requests for extracted url + for link in download_links: + + # request image link from imgur + res2 = requests.get(link) + + try: + res2.raise_for_status() + + # save to file with url base name in folder results + imgFile = open(os.path.join(abs_output_path, os.path.basename(link)), 'wb') + for chunk in res2.iter_content(100000): + imgFile.write(chunk) + imgFile.close() + + except Exception as exc: + print('There was a problem: %s' % (exc)) + + + + except Exception as exc: + print('There was a problem: %s' % (exc)) + + +if __name__ == '__main__': + downloader('messi', 10, 'results') \ No newline at end of file diff --git a/projects/image-site-downloader/requirements.txt b/projects/image-site-downloader/requirements.txt new file mode 100644 index 00000000..588cb5da --- /dev/null +++ b/projects/image-site-downloader/requirements.txt @@ -0,0 +1 @@ +bs4 \ No newline at end of file diff --git a/projects/instant-messenger-bot/active_identifier.png b/projects/instant-messenger-bot/active_identifier.png new file mode 100755 index 00000000..b55800f4 Binary files /dev/null and b/projects/instant-messenger-bot/active_identifier.png differ diff --git a/projects/instant-messenger-bot/requirements.txt b/projects/instant-messenger-bot/requirements.txt new file mode 100644 index 00000000..cb9eb4aa --- /dev/null +++ b/projects/instant-messenger-bot/requirements.txt @@ -0,0 +1 @@ +pyautogui \ No newline at end of file diff --git a/projects/instant-messenger-bot/slack_messenger.py b/projects/instant-messenger-bot/slack_messenger.py new file mode 100755 index 00000000..179349ff --- /dev/null +++ b/projects/instant-messenger-bot/slack_messenger.py @@ -0,0 +1,49 @@ +import time + +import pyautogui + + +def send_message(contact, message): + """Sends message to an active slack contact + Args: + contact (str): contacts name on slack + message (str): message to send to friend + Returns: + None + """ + try: + print('5 seconds to navigate to slack app..') + time.sleep(5) + + # Use JumpTo slack feature + pyautogui.hotkey('command', 'k') + time.sleep(1) + # Enter contact name in search box, click enter + pyautogui.typewrite(contact) + time.sleep(1) + pyautogui.typewrite(['enter']) + time.sleep(1) + + active = pyautogui.locateOnScreen('active_identifier.png') + + if not active: + print(f'{contact} is not active, skipped contact') + return + + print('Contact is active, sending message...') + pyautogui.typewrite(['tab']) + pyautogui.typewrite(message) + pyautogui.typewrite(['enter']) + + except KeyboardInterrupt: + print('Process was cancelled..') + + +if __name__ == "__main__": + + contacts = input('Enter contact list, separated by space >> Messi Onazi John: ').split(' ') + message = input('Enter the message you wish to send out to them: ') + + for c in contacts: + contact = c.strip() + send_message(contact, message) \ No newline at end of file diff --git a/projects/link-verification/requirements.txt b/projects/link-verification/requirements.txt new file mode 100644 index 00000000..588cb5da --- /dev/null +++ b/projects/link-verification/requirements.txt @@ -0,0 +1 @@ +bs4 \ No newline at end of file diff --git a/projects/link-verification/verify_links.py b/projects/link-verification/verify_links.py new file mode 100755 index 00000000..8da4a4e1 --- /dev/null +++ b/projects/link-verification/verify_links.py @@ -0,0 +1,46 @@ +import requests +import bs4 + +def verify(url): + """verifies all links within a page, prints broken links + Args: + url (str): url of page to check + Returns: + None + """ + + res1 = requests.get(url) + + try: + res1.raise_for_status() + + soup = bs4.BeautifulSoup(res1.text, 'html.parser') + pageLinks = [link.get('href') for link in soup.select('a') if link.get('href')] + + brokenCount = 0 + goodCount = 0 + + for link in pageLinks: + + if link.startswith('http'): + res2 = requests.get(link) + + try: + + res2.raise_for_status() + print(f'Good: {link}') + goodCount += 1 + + except Exception as exc: + print(f'Broken: {link}') + brokenCount += 1 + + print(f'{goodCount} Good. {brokenCount} Broken') + + + except Exception as exc: + print('There was a problem: %s' % (exc)) + + +if __name__ == "__main__": + verify('https://automatetheboringstuff.com/chapter11/') \ No newline at end of file diff --git a/projects/looking-busy/look_busy.py b/projects/looking-busy/look_busy.py new file mode 100755 index 00000000..b6111501 --- /dev/null +++ b/projects/looking-busy/look_busy.py @@ -0,0 +1,23 @@ +import time +import pyautogui + + +def make_busy(): + """Moves mouse every 10 seconds to keep apps active + Args: + None + Returns: + None + """ + print('Press CTRL-C to quit.') + try: + while True: + pyautogui.moveRel(5, 0, 0.5) + pyautogui.moveRel(-5, 0, 0.5) + time.sleep(10) + except KeyboardInterrupt: + print('Process has quit...') + + +if __name__ == "__main__": + make_busy() \ No newline at end of file diff --git a/projects/looking-busy/requirements.txt b/projects/looking-busy/requirements.txt new file mode 100644 index 00000000..cb9eb4aa --- /dev/null +++ b/projects/looking-busy/requirements.txt @@ -0,0 +1 @@ +pyautogui \ No newline at end of file