├── 09-organize-file ├── demo │ ├── spam001.txt │ └── spam003.txt ├── createZipFile.py ├── README.md ├── send2trashDemo.py ├── traverseDir.py ├── zipfileDemo.py ├── filesize.py ├── copy.py ├── sequence.py ├── backupToZip.py └── renameDates.py ├── 08-file ├── mcb.bak ├── mcb.dir ├── mydata.bak ├── mydata.dir ├── bacon.txt ├── mcb.dat ├── mydata.dat ├── myCats.py ├── sonnet29.txt ├── pprintDemo.py ├── shelfFile.py ├── baconFile.py ├── madlibs.py ├── find.py ├── mcb.pyw └── randomQuizGenerator.py ├── 06-str ├── README.md ├── readme.txt ├── usingPyperclip.py ├── catnapping.py ├── picnicTable.py ├── validateInput.py ├── bulletPointAdder.py ├── pw.py └── printTable.py ├── 13-pdf-word ├── guests.txt ├── demo.docx ├── encrypted.pdf ├── headings.docx ├── restyled.docx ├── twoPage.docx ├── watermark.pdf ├── encryptTest.pdf ├── helloworld.docx ├── rotatedPage.pdf ├── combineminutes.pdf ├── guestTemplete.docx ├── meetingminutes.pdf ├── meetingminutes2.pdf ├── encryptedminutes.pdf ├── guestsInvitaion.docx ├── watermarkedCover.pdf ├── multipleParagraphs.docx ├── createDocx.py ├── extractText.py ├── readDocx.py ├── addBreakToDocx.py ├── addHeaderToDocx.py ├── addContentToDocx.py ├── rotatePdf.py ├── encryptPdf.py ├── README.md ├── decryptPdfWithDict.py ├── docxDemo.py ├── mergePdf.py ├── watermarkPdf.py ├── createInvitation.py ├── combinePdfs.py └── batchEncryptPdf.py ├── 17-image ├── text.png ├── tiled.png ├── catlogo.png ├── cropped.png ├── drawing.png ├── pasted.png ├── putPixel.png ├── rotated6.png ├── svelte.png ├── zophie.jpg ├── zophie.png ├── rotated180.png ├── rotated270.png ├── rotated90.png ├── purpleImage.png ├── quartersized.png ├── png2jpg.py ├── rotated6_expanded.png ├── transparentImage.png ├── README.md ├── drawAndText.py ├── resizeAndAddLogo.py └── imageOp.py ├── 12-excel ├── example.xlsx ├── styled.xlsx ├── trans.xlsx ├── example_copy.xlsx ├── produceSales.xlsx ├── sampleChart.xlsx ├── writeFormula.xlsx ├── censuspopdata.xlsx ├── trans.xlsx.trans.xlsx ├── updatedProduceSales.xlsx ├── multiplicationTable-10.xlsx ├── multiplicationTable-20.xlsx ├── multiplicationTable-6.xlsx ├── multiplicationTable-20.xlsx.blank.xlsx ├── multiplicationTable-20.xlsx.blank.xlsx.trans.xlsx ├── writeExcel.py ├── formula.py ├── stylingUnit.py ├── readExcel.py ├── README.md ├── excelToText.py ├── textToExcel.py ├── multiplicationTable.py ├── updateProduce.py ├── transposition.py ├── blankRowInserter.py └── readCensusExcel.py ├── 14-csv-json ├── output.csv ├── example.tsv ├── removeCsvHeader.zip ├── excelSpreadsheets.zip ├── readCsv.py ├── example.csv ├── README.md ├── jsonLoadsAndDumps.py ├── writeCsv.py ├── delimiterCsv.py ├── excelToCsv.py ├── removeCsvHeader.py └── quickWeather.py ├── README.md ├── 02-control-flow ├── printRandom.py ├── yourName.py ├── yourName2.py ├── exitExample.py └── fiveTimes.py ├── automate_online-materials ├── guests.txt ├── printRandom.py ├── alarm.wav ├── demo.docx ├── fiveTimes.py ├── helloFunc2.py ├── zophie.png ├── catlogo.png ├── example.xlsx ├── example.zip ├── merged.xlsx ├── styled.xlsx ├── styles.xlsx ├── twoPage.docx ├── dimensions.xlsx ├── encrypted.pdf ├── headings.docx ├── helloworld.docx ├── restyled.docx ├── watermark.pdf ├── duesRecords.xlsx ├── produceSales.xlsx ├── sameName2.py ├── sameName4.py ├── sampleChart.xlsx ├── censuspopdata.xlsx ├── combinedminutes.pdf ├── encryptedminutes.pdf ├── freezeExample.xlsx ├── meetingminutes.pdf ├── meetingminutes2.pdf ├── removeCsvHeader.zip ├── excelSpreadsheets.zip ├── multipleParagraphs.docx ├── updatedProduceSales.xlsx ├── errorExample.py ├── passingReference.py ├── catnapping.py ├── helloFunc.py ├── littleKid.py ├── exitExample.py ├── example.csv ├── myPets.py ├── coinFlip.py ├── zeroDivide.py ├── readDocx.py ├── buggyAddingProgram.py ├── characterCount.py ├── threadDemo.py ├── getDocxText.py ├── vampire.py ├── vampire2.py ├── sameName3.py ├── prettyCharacterCount.py ├── swordfish.py ├── sameName.py ├── example.html ├── calcProd.py ├── allMyCats2.py ├── countdown.py ├── magic8Ball2.py ├── picnicTable.py ├── inventory.py ├── hello.py ├── validateInput.py ├── mapIt.py ├── bulletPointAdder.py ├── mouseNow.py ├── allMyCats1.py ├── factorialLog.py ├── birthdays.py ├── textMyself.py ├── lucky.py ├── pw.py ├── boxPrint.py ├── updateProduce.py ├── guessTheNumber.py ├── mouseNow2.py ├── magic8Ball.py ├── ticTacToe.py ├── mcb.pyw ├── isPhoneNumber.py ├── stopwatch.py ├── combinePdfs.py ├── removeCsvHeader.py ├── quickWeather.py ├── downloadXkcd.py ├── phoneAndEmail.py ├── readCensusExcel.py ├── sendDuesReminders.py ├── backupToZip.py ├── renameDates.py ├── resizeAndAddLogo.py ├── multidownloadXkcd.py ├── formFiller.py ├── randomQuizGenerator.py └── torrentStarter.py ├── 03-function ├── helloFunc2.py ├── sameName4.py ├── sameName2.py ├── helloFunc.py ├── zeroDivide.py ├── sameName3.py ├── sameName.py ├── collatz.py ├── guessTheNumber.py └── magic8Ball.py ├── 16-email-sms ├── duesRecords.xlsx ├── README.md ├── textMyself.py └── sendDuesReminders.py ├── 10-debug ├── errorExample.py ├── errorInfo.txt ├── coinFlip.py ├── buggyAddingProgram.py ├── format_exc.py ├── myProgramLog.txt ├── carSim.py ├── guessCoin.py ├── boxPrint.py ├── factorialLog.py └── README.md ├── 15-time ├── timeSleep.py ├── about30YearsLater.py ├── thousandDaysLater.py ├── until.py ├── threadWithParameters.py ├── README.md ├── threadDemo.py ├── calcProd.py ├── countdown.py ├── stopwatch.py └── multidownloadXkcd.py ├── 04-list ├── passingReference.py ├── commaList.py ├── allMyCats2.py ├── magic8Ball2.py ├── allMyCats1.py └── printGrid.py ├── 11-web ├── seleniumClickLink.py ├── downloadAllLinks.py ├── bs4Demo.py ├── downloadImages.py ├── example.html ├── seleniumFindElement.py ├── mapIt.py ├── seleniumLoginGithub.py ├── requestsDemo.py ├── play2048.py ├── lucky.py ├── sendEmailByCommandLine.py ├── README.md └── downloadXkcd.py ├── 18-GUI-control ├── moveRel.py ├── moveTo.py ├── commentAfterDelay.py ├── spiralDraw.py ├── README.md ├── mouseNow.py ├── mouseNow2.py └── formFiller.py ├── 05-dict ├── characterCount.py ├── prettyCharacterCount.py ├── inventory.py ├── birthdays.py ├── dragonLoot.py └── ticTacToe.py ├── 07-regex ├── stripRe.py ├── passwordValidation.py ├── readme.md ├── isPhoneNumber.py └── phoneAndEmail.py ├── 01-basic └── hello.py └── .gitignore /09-organize-file/demo/spam001.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /09-organize-file/demo/spam003.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /08-file/mcb.bak: -------------------------------------------------------------------------------- 1 | 'b', (512, 17) 2 | -------------------------------------------------------------------------------- /08-file/mcb.dir: -------------------------------------------------------------------------------- 1 | 'b', (512, 17) 2 | -------------------------------------------------------------------------------- /08-file/mydata.bak: -------------------------------------------------------------------------------- 1 | 'cats', (0, 45) 2 | -------------------------------------------------------------------------------- /08-file/mydata.dir: -------------------------------------------------------------------------------- 1 | 'cats', (0, 45) 2 | -------------------------------------------------------------------------------- /08-file/bacon.txt: -------------------------------------------------------------------------------- 1 | Hello world! 2 | Bacon is not a vegetable. -------------------------------------------------------------------------------- /06-str/README.md: -------------------------------------------------------------------------------- 1 | * pyperclip 2 | 剪贴板内容管理接口 3 | pip install pyperclip -------------------------------------------------------------------------------- /08-file/mcb.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/08-file/mcb.dat -------------------------------------------------------------------------------- /06-str/readme.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/06-str/readme.txt -------------------------------------------------------------------------------- /08-file/mydata.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/08-file/mydata.dat -------------------------------------------------------------------------------- /13-pdf-word/guests.txt: -------------------------------------------------------------------------------- 1 | Prof. Plum 2 | Miss Scarlet 3 | Col. Mustard 4 | Al Sweigart 5 | Robocop -------------------------------------------------------------------------------- /17-image/text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/17-image/text.png -------------------------------------------------------------------------------- /17-image/tiled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/17-image/tiled.png -------------------------------------------------------------------------------- /12-excel/example.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/12-excel/example.xlsx -------------------------------------------------------------------------------- /12-excel/styled.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/12-excel/styled.xlsx -------------------------------------------------------------------------------- /12-excel/trans.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/12-excel/trans.xlsx -------------------------------------------------------------------------------- /13-pdf-word/demo.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/13-pdf-word/demo.docx -------------------------------------------------------------------------------- /14-csv-json/output.csv: -------------------------------------------------------------------------------- 1 | spam,eggs,bacon,ham 2 | "Hello, world!",eggs,bacon,ham 3 | 1,2,3.141592,4 4 | -------------------------------------------------------------------------------- /17-image/catlogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/17-image/catlogo.png -------------------------------------------------------------------------------- /17-image/cropped.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/17-image/cropped.png -------------------------------------------------------------------------------- /17-image/drawing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/17-image/drawing.png -------------------------------------------------------------------------------- /17-image/pasted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/17-image/pasted.png -------------------------------------------------------------------------------- /17-image/putPixel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/17-image/putPixel.png -------------------------------------------------------------------------------- /17-image/rotated6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/17-image/rotated6.png -------------------------------------------------------------------------------- /17-image/svelte.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/17-image/svelte.png -------------------------------------------------------------------------------- /17-image/zophie.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/17-image/zophie.jpg -------------------------------------------------------------------------------- /17-image/zophie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/17-image/zophie.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AutomatePython 2 | * Python 编程快速上手——让繁琐工作自动化 3 | * http://inventwithpython.com 4 | -------------------------------------------------------------------------------- /02-control-flow/printRandom.py: -------------------------------------------------------------------------------- 1 | import random 2 | for i in range(5): 3 | print(random.randint(1, 10)) 4 | -------------------------------------------------------------------------------- /08-file/myCats.py: -------------------------------------------------------------------------------- 1 | cats = [{'desc': 'chubby', 'name': 'Zophie'}, {'desc': 'fluffy', 'name': 'Pooka'}] 2 | -------------------------------------------------------------------------------- /17-image/rotated180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/17-image/rotated180.png -------------------------------------------------------------------------------- /17-image/rotated270.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/17-image/rotated270.png -------------------------------------------------------------------------------- /17-image/rotated90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/17-image/rotated90.png -------------------------------------------------------------------------------- /automate_online-materials/guests.txt: -------------------------------------------------------------------------------- 1 | Prof. Plum 2 | Miss Scarlet 3 | Col. Mustard 4 | Al Sweigart 5 | Robocop -------------------------------------------------------------------------------- /12-excel/example_copy.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/12-excel/example_copy.xlsx -------------------------------------------------------------------------------- /12-excel/produceSales.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/12-excel/produceSales.xlsx -------------------------------------------------------------------------------- /12-excel/sampleChart.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/12-excel/sampleChart.xlsx -------------------------------------------------------------------------------- /12-excel/writeFormula.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/12-excel/writeFormula.xlsx -------------------------------------------------------------------------------- /13-pdf-word/encrypted.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/13-pdf-word/encrypted.pdf -------------------------------------------------------------------------------- /13-pdf-word/headings.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/13-pdf-word/headings.docx -------------------------------------------------------------------------------- /13-pdf-word/restyled.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/13-pdf-word/restyled.docx -------------------------------------------------------------------------------- /13-pdf-word/twoPage.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/13-pdf-word/twoPage.docx -------------------------------------------------------------------------------- /13-pdf-word/watermark.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/13-pdf-word/watermark.pdf -------------------------------------------------------------------------------- /17-image/purpleImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/17-image/purpleImage.png -------------------------------------------------------------------------------- /17-image/quartersized.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/17-image/quartersized.png -------------------------------------------------------------------------------- /automate_online-materials/printRandom.py: -------------------------------------------------------------------------------- 1 | import random 2 | for i in range(5): 3 | print(random.randint(1, 10)) -------------------------------------------------------------------------------- /03-function/helloFunc2.py: -------------------------------------------------------------------------------- 1 | def hello(name): 2 | print('Hello ' + name) 3 | 4 | hello('Alice') 5 | hello('Bob') 6 | -------------------------------------------------------------------------------- /12-excel/censuspopdata.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/12-excel/censuspopdata.xlsx -------------------------------------------------------------------------------- /13-pdf-word/encryptTest.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/13-pdf-word/encryptTest.pdf -------------------------------------------------------------------------------- /13-pdf-word/helloworld.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/13-pdf-word/helloworld.docx -------------------------------------------------------------------------------- /13-pdf-word/rotatedPage.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/13-pdf-word/rotatedPage.pdf -------------------------------------------------------------------------------- /14-csv-json/example.tsv: -------------------------------------------------------------------------------- 1 | apples oranges grapes 2 | 3 | eggs bacon ham 4 | 5 | spam spam spam spam spam spam 6 | 7 | -------------------------------------------------------------------------------- /17-image/png2jpg.py: -------------------------------------------------------------------------------- 1 | from PIL import Image 2 | 3 | catIm = Image.open('zophie.png') 4 | catIm.save('zophie.jpg') 5 | -------------------------------------------------------------------------------- /12-excel/trans.xlsx.trans.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/12-excel/trans.xlsx.trans.xlsx -------------------------------------------------------------------------------- /13-pdf-word/combineminutes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/13-pdf-word/combineminutes.pdf -------------------------------------------------------------------------------- /13-pdf-word/guestTemplete.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/13-pdf-word/guestTemplete.docx -------------------------------------------------------------------------------- /13-pdf-word/meetingminutes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/13-pdf-word/meetingminutes.pdf -------------------------------------------------------------------------------- /13-pdf-word/meetingminutes2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/13-pdf-word/meetingminutes2.pdf -------------------------------------------------------------------------------- /14-csv-json/removeCsvHeader.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/14-csv-json/removeCsvHeader.zip -------------------------------------------------------------------------------- /16-email-sms/duesRecords.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/16-email-sms/duesRecords.xlsx -------------------------------------------------------------------------------- /17-image/rotated6_expanded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/17-image/rotated6_expanded.png -------------------------------------------------------------------------------- /17-image/transparentImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/17-image/transparentImage.png -------------------------------------------------------------------------------- /06-str/usingPyperclip.py: -------------------------------------------------------------------------------- 1 | import pyperclip #pip install pyperclip 2 | pyperclip.copy('Hello world!') 3 | pyperclip.paste() 4 | -------------------------------------------------------------------------------- /12-excel/updatedProduceSales.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/12-excel/updatedProduceSales.xlsx -------------------------------------------------------------------------------- /13-pdf-word/encryptedminutes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/13-pdf-word/encryptedminutes.pdf -------------------------------------------------------------------------------- /13-pdf-word/guestsInvitaion.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/13-pdf-word/guestsInvitaion.docx -------------------------------------------------------------------------------- /13-pdf-word/watermarkedCover.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/13-pdf-word/watermarkedCover.pdf -------------------------------------------------------------------------------- /14-csv-json/excelSpreadsheets.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/14-csv-json/excelSpreadsheets.zip -------------------------------------------------------------------------------- /03-function/sameName4.py: -------------------------------------------------------------------------------- 1 | def spam(): 2 | print(eggs) # ERROR! 3 | eggs = 'spam local' 4 | 5 | eggs = 'global' 6 | spam() 7 | -------------------------------------------------------------------------------- /12-excel/multiplicationTable-10.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/12-excel/multiplicationTable-10.xlsx -------------------------------------------------------------------------------- /12-excel/multiplicationTable-20.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/12-excel/multiplicationTable-20.xlsx -------------------------------------------------------------------------------- /12-excel/multiplicationTable-6.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/12-excel/multiplicationTable-6.xlsx -------------------------------------------------------------------------------- /13-pdf-word/multipleParagraphs.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/13-pdf-word/multipleParagraphs.docx -------------------------------------------------------------------------------- /automate_online-materials/alarm.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/automate_online-materials/alarm.wav -------------------------------------------------------------------------------- /automate_online-materials/demo.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/automate_online-materials/demo.docx -------------------------------------------------------------------------------- /automate_online-materials/fiveTimes.py: -------------------------------------------------------------------------------- 1 | print('My name is') 2 | for i in range(5): 3 | print('Jimmy Five Times (' + str(i) + ')') -------------------------------------------------------------------------------- /automate_online-materials/helloFunc2.py: -------------------------------------------------------------------------------- 1 | def hello(name): 2 | print('Hello ' + name) 3 | 4 | hello('Alice') 5 | hello('Bob') 6 | -------------------------------------------------------------------------------- /automate_online-materials/zophie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/automate_online-materials/zophie.png -------------------------------------------------------------------------------- /03-function/sameName2.py: -------------------------------------------------------------------------------- 1 | def spam(): 2 | global eggs 3 | eggs = 'spam' 4 | 5 | eggs = 'global' 6 | spam() 7 | print(eggs) 8 | -------------------------------------------------------------------------------- /13-pdf-word/createDocx.py: -------------------------------------------------------------------------------- 1 | import docx 2 | 3 | doc = docx.Document() 4 | doc.add_paragraph('Hello world!') 5 | doc.save('helloworld.docx') -------------------------------------------------------------------------------- /automate_online-materials/catlogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/automate_online-materials/catlogo.png -------------------------------------------------------------------------------- /automate_online-materials/example.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/automate_online-materials/example.xlsx -------------------------------------------------------------------------------- /automate_online-materials/example.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/automate_online-materials/example.zip -------------------------------------------------------------------------------- /automate_online-materials/merged.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/automate_online-materials/merged.xlsx -------------------------------------------------------------------------------- /automate_online-materials/styled.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/automate_online-materials/styled.xlsx -------------------------------------------------------------------------------- /automate_online-materials/styles.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/automate_online-materials/styles.xlsx -------------------------------------------------------------------------------- /automate_online-materials/twoPage.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/automate_online-materials/twoPage.docx -------------------------------------------------------------------------------- /automate_online-materials/dimensions.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/automate_online-materials/dimensions.xlsx -------------------------------------------------------------------------------- /automate_online-materials/encrypted.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/automate_online-materials/encrypted.pdf -------------------------------------------------------------------------------- /automate_online-materials/headings.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/automate_online-materials/headings.docx -------------------------------------------------------------------------------- /automate_online-materials/helloworld.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/automate_online-materials/helloworld.docx -------------------------------------------------------------------------------- /automate_online-materials/restyled.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/automate_online-materials/restyled.docx -------------------------------------------------------------------------------- /automate_online-materials/watermark.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/automate_online-materials/watermark.pdf -------------------------------------------------------------------------------- /10-debug/errorExample.py: -------------------------------------------------------------------------------- 1 | def spam(): 2 | bacon() 3 | 4 | def bacon(): 5 | raise Exception('This is the error message.') 6 | 7 | spam() 8 | -------------------------------------------------------------------------------- /15-time/timeSleep.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | for i in range(3): 4 | print('Tick') 5 | time.sleep(1) 6 | print('Tock') 7 | time.sleep(1) 8 | -------------------------------------------------------------------------------- /17-image/README.md: -------------------------------------------------------------------------------- 1 | # Pillow 2 | `pip install pillow` 3 |
4 | from PIL import ImageColor
5 | from PIL import Image
6 | 
7 | 8 | 9 | -------------------------------------------------------------------------------- /automate_online-materials/duesRecords.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/automate_online-materials/duesRecords.xlsx -------------------------------------------------------------------------------- /automate_online-materials/produceSales.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/automate_online-materials/produceSales.xlsx -------------------------------------------------------------------------------- /automate_online-materials/sameName2.py: -------------------------------------------------------------------------------- 1 | def spam(): 2 | global eggs 3 | eggs = 'spam' 4 | 5 | eggs = 'global' 6 | spam() 7 | print(eggs) 8 | -------------------------------------------------------------------------------- /automate_online-materials/sameName4.py: -------------------------------------------------------------------------------- 1 | def spam(): 2 | print(eggs) # ERROR! 3 | eggs = 'spam local' 4 | 5 | eggs = 'global' 6 | spam() 7 | -------------------------------------------------------------------------------- /automate_online-materials/sampleChart.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/automate_online-materials/sampleChart.xlsx -------------------------------------------------------------------------------- /04-list/passingReference.py: -------------------------------------------------------------------------------- 1 | def eggs(someParameter): 2 | someParameter.append('Hello') 3 | 4 | spam = [1, 2, 3] 5 | eggs(spam) 6 | print(spam) 7 | -------------------------------------------------------------------------------- /automate_online-materials/censuspopdata.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/automate_online-materials/censuspopdata.xlsx -------------------------------------------------------------------------------- /automate_online-materials/combinedminutes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/automate_online-materials/combinedminutes.pdf -------------------------------------------------------------------------------- /automate_online-materials/encryptedminutes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/automate_online-materials/encryptedminutes.pdf -------------------------------------------------------------------------------- /automate_online-materials/freezeExample.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/automate_online-materials/freezeExample.xlsx -------------------------------------------------------------------------------- /automate_online-materials/meetingminutes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/automate_online-materials/meetingminutes.pdf -------------------------------------------------------------------------------- /automate_online-materials/meetingminutes2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/automate_online-materials/meetingminutes2.pdf -------------------------------------------------------------------------------- /automate_online-materials/removeCsvHeader.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/automate_online-materials/removeCsvHeader.zip -------------------------------------------------------------------------------- /12-excel/multiplicationTable-20.xlsx.blank.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/12-excel/multiplicationTable-20.xlsx.blank.xlsx -------------------------------------------------------------------------------- /15-time/about30YearsLater.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | 3 | aboutThirtyYears = datetime.timedelta(days=365*30) 4 | print(datetime.datetime.now() + aboutThirtyYears) -------------------------------------------------------------------------------- /automate_online-materials/excelSpreadsheets.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/automate_online-materials/excelSpreadsheets.zip -------------------------------------------------------------------------------- /02-control-flow/yourName.py: -------------------------------------------------------------------------------- 1 | name = '' 2 | while name != 'your name': 3 | print('Please type your name.') 4 | name = input() 5 | print('Thank you!') 6 | -------------------------------------------------------------------------------- /03-function/helloFunc.py: -------------------------------------------------------------------------------- 1 | def hello(): 2 | print('Howdy!') 3 | print('Howdy!!!') 4 | print('Hello there.') 5 | 6 | hello() 7 | hello() 8 | hello() 9 | -------------------------------------------------------------------------------- /06-str/catnapping.py: -------------------------------------------------------------------------------- 1 | print('''Dear Alice, 2 | 3 | Eve's cat has been arrested for catnapping, cat burglary, and extortion. 4 | 5 | Sincerely, 6 | Bob''') 7 | -------------------------------------------------------------------------------- /15-time/thousandDaysLater.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | 3 | dt = datetime.datetime.now() 4 | thousandDays = datetime.timedelta(days=1000) 5 | print(dt + thousandDays) -------------------------------------------------------------------------------- /automate_online-materials/multipleParagraphs.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/automate_online-materials/multipleParagraphs.docx -------------------------------------------------------------------------------- /automate_online-materials/updatedProduceSales.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/automate_online-materials/updatedProduceSales.xlsx -------------------------------------------------------------------------------- /automate_online-materials/errorExample.py: -------------------------------------------------------------------------------- 1 | def spam(): 2 | bacon() 3 | 4 | def bacon(): 5 | raise Exception('This is the error message.') 6 | 7 | spam() 8 | -------------------------------------------------------------------------------- /automate_online-materials/passingReference.py: -------------------------------------------------------------------------------- 1 | def eggs(someParameter): 2 | someParameter.append('Hello') 3 | 4 | spam = [1, 2, 3] 5 | eggs(spam) 6 | print(spam) 7 | -------------------------------------------------------------------------------- /12-excel/multiplicationTable-20.xlsx.blank.xlsx.trans.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguohui/AutomatePython/HEAD/12-excel/multiplicationTable-20.xlsx.blank.xlsx.trans.xlsx -------------------------------------------------------------------------------- /15-time/until.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import time 3 | tm = datetime.datetime(2017, 7, 8, 8, 27, 0) 4 | while datetime.datetime.now() < tm: 5 | time.sleep(1) 6 | print('Done') -------------------------------------------------------------------------------- /16-email-sms/README.md: -------------------------------------------------------------------------------- 1 | # SMTP 2 |
 3 | import smtplib
 4 | 
5 | 6 | # IMAP 7 |
 8 | pyzmail
 9 | 
10 | 11 | # SMS 12 |
13 | Twilio
14 | 
-------------------------------------------------------------------------------- /automate_online-materials/catnapping.py: -------------------------------------------------------------------------------- 1 | print('''Dear Alice, 2 | 3 | Eve's cat has been arrested for catnapping, cat burglary, and extortion. 4 | 5 | Sincerely, 6 | Bob''') 7 | -------------------------------------------------------------------------------- /automate_online-materials/helloFunc.py: -------------------------------------------------------------------------------- 1 | def hello(): 2 | print('Howdy!') 3 | print('Howdy!!!') 4 | print('Hello there.') 5 | 6 | hello() 7 | hello() 8 | hello() 9 | -------------------------------------------------------------------------------- /02-control-flow/yourName2.py: -------------------------------------------------------------------------------- 1 | while True: 2 | print('Please type your name.') 3 | name = input() 4 | if name == 'your name': 5 | break 6 | print('Thank you!') 7 | -------------------------------------------------------------------------------- /09-organize-file/createZipFile.py: -------------------------------------------------------------------------------- 1 | import os 2 | import zipfile 3 | 4 | newZip = zipfile.ZipFile('new.zip', 'w') 5 | newZip.write('README.md', compress_type=zipfile.ZIP_DEFLATED) 6 | newZip.close() -------------------------------------------------------------------------------- /15-time/threadWithParameters.py: -------------------------------------------------------------------------------- 1 | import threading 2 | 3 | threadObj = threading.Thread(target=print, args=['Cats', 'Dogs', 'Frogs'], 4 | kwargs={'sep': ' & '}) 5 | threadObj.start() 6 | 7 | -------------------------------------------------------------------------------- /09-organize-file/README.md: -------------------------------------------------------------------------------- 1 | # shutil 2 | * shell工具 3 | * `import shutil` 4 | 5 | # send2trash 6 | * 将文件夹和文件发送到垃圾箱或回收站 7 | * `pip install send2trash` 8 | 9 | # zipfile 10 | * `import zipfile` -------------------------------------------------------------------------------- /14-csv-json/readCsv.py: -------------------------------------------------------------------------------- 1 | import csv 2 | 3 | exampleFile = open('example.csv') 4 | exampleReader = csv.reader(exampleFile) 5 | 6 | for row in exampleReader: 7 | print(row) 8 | 9 | exampleFile.close() -------------------------------------------------------------------------------- /10-debug/errorInfo.txt: -------------------------------------------------------------------------------- 1 | Traceback (most recent call last): 2 | File ".\format_exc.py", line 3, in 3 | raise Exception('This is the error message.') 4 | Exception: This is the error message. 5 | -------------------------------------------------------------------------------- /09-organize-file/send2trashDemo.py: -------------------------------------------------------------------------------- 1 | import send2trash 2 | 3 | baconFile = open('bacon.txt', 'a') 4 | baconFile.write('Bacon is not a vegetable.') 5 | baconFile.close() 6 | 7 | send2trash.send2trash('bacon.txt') -------------------------------------------------------------------------------- /02-control-flow/exitExample.py: -------------------------------------------------------------------------------- 1 | import sys 2 | while True: 3 | print('Type exit to exit.') 4 | response = input() 5 | if response == 'exit': 6 | sys.exit() 7 | print('You typed ' + response + '.') -------------------------------------------------------------------------------- /12-excel/writeExcel.py: -------------------------------------------------------------------------------- 1 | import openpyxl 2 | 3 | wb = openpyxl.Workbook() 4 | sheet = wb.get_active_sheet() 5 | 6 | sheet.title = 'Spam Spam Spam' 7 | print(wb.get_sheet_names()) 8 | 9 | wb.save('example_copy.xlsx') -------------------------------------------------------------------------------- /08-file/sonnet29.txt: -------------------------------------------------------------------------------- 1 | When, in disgrace with fortune and men's eyes, 2 | I all alone beweep my outcast state, 3 | And trouble deaf heaven with my bootless cries, 4 | And look upon myself and curse my fate, 5 | hello world -------------------------------------------------------------------------------- /12-excel/formula.py: -------------------------------------------------------------------------------- 1 | import openpyxl 2 | 3 | wb = openpyxl.Workbook() 4 | sheet = wb.active 5 | sheet['A1'] = 200 6 | sheet['A2'] = 300 7 | sheet['A3'] = '=SUM(A1:A2)' 8 | wb.save('writeFormula.xlsx') 9 | 10 | -------------------------------------------------------------------------------- /automate_online-materials/littleKid.py: -------------------------------------------------------------------------------- 1 | if name == 'Alice': 2 | print('Hi, Alice.') 3 | elif age < 12: 4 | print('You are not Alice, kiddo.') 5 | else: 6 | print('You are neither Alice nor a little kid.') 7 | -------------------------------------------------------------------------------- /automate_online-materials/exitExample.py: -------------------------------------------------------------------------------- 1 | import sys 2 | while True: 3 | print('Type exit to exit.') 4 | response = input() 5 | if response == 'exit': 6 | sys.exit() 7 | print('You typed ' + response + '.') -------------------------------------------------------------------------------- /11-web/seleniumClickLink.py: -------------------------------------------------------------------------------- 1 | from selenium import webdriver 2 | browser = webdriver.Firefox() 3 | browser.get('http://inventwithpython.com') 4 | 5 | linkElem = browser.find_element_by_link_text('Read It Online') 6 | linkElem.click() -------------------------------------------------------------------------------- /14-csv-json/example.csv: -------------------------------------------------------------------------------- 1 | 4/5/2014 13:34,Apples,73 2 | 4/5/2014 3:41,Cherries,85 3 | 4/6/2014 12:46,Pears,14 4 | 4/8/2014 8:59,Oranges,52 5 | 4/10/2014 2:07,Apples,152 6 | 4/10/2014 18:10,Bananas,23 7 | 4/10/2014 2:40,Strawberries,98 8 | -------------------------------------------------------------------------------- /02-control-flow/fiveTimes.py: -------------------------------------------------------------------------------- 1 | print('My name is') 2 | for i in range(5): 3 | print('Jimmy Five Times (' + str(i) + ')') 4 | 5 | print() 6 | i = 0 7 | while i < 5: 8 | print('Jimmy Five Times (' + str(i) + ')') 9 | i += 1 10 | -------------------------------------------------------------------------------- /04-list/commaList.py: -------------------------------------------------------------------------------- 1 | def commaList(items): 2 | ret = '' 3 | for item in items[:-1]: 4 | ret += item + ', ' 5 | return ret + 'and ' + items[-1] 6 | 7 | spam = ['apples', 'bananas', 'tofu', 'cats'] 8 | print(commaList(spam)) 9 | -------------------------------------------------------------------------------- /14-csv-json/README.md: -------------------------------------------------------------------------------- 1 | # csv 2 |
 3 | import csv
 4 | csvFileObj = open(csvFilename)
 5 | readerObj = csv.reader(csvFileObj)import csv
 6 | 
7 | 8 | # json 9 |
10 | import json
11 | json.loads()
12 | json.dumps()
13 | 
-------------------------------------------------------------------------------- /13-pdf-word/extractText.py: -------------------------------------------------------------------------------- 1 | import PyPDF2 2 | 3 | pdfFileObj = open('meetingminutes.pdf', 'rb') 4 | pdfReader = PyPDF2.PdfFileReader(pdfFileObj) 5 | print(pdfReader.numPages) 6 | 7 | pageObj = pdfReader.getPage(0) 8 | print(pageObj.extractText()) 9 | -------------------------------------------------------------------------------- /automate_online-materials/example.csv: -------------------------------------------------------------------------------- 1 | 4/5/2014 13:34,Apples,73 2 | 4/5/2014 3:41,Cherries,85 3 | 4/6/2014 12:46,Pears,14 4 | 4/8/2014 8:59,Oranges,52 5 | 4/10/2014 2:07,Apples,152 6 | 4/10/2014 18:10,Bananas,23 7 | 4/10/2014 2:40,Strawberries,98 8 | -------------------------------------------------------------------------------- /10-debug/coinFlip.py: -------------------------------------------------------------------------------- 1 | import random 2 | heads = 0 3 | for i in range(1, 1001): 4 | if random.randint(0, 1) == 1: 5 | heads = heads + 1 6 | if i == 500: 7 | print('Halfway done!') 8 | print('Heads came up ' + str(heads) + ' times.') 9 | -------------------------------------------------------------------------------- /automate_online-materials/myPets.py: -------------------------------------------------------------------------------- 1 | myPets = ['Zophie', 'Pooka', 'Fat-tail'] 2 | print('Enter a pet name:') 3 | name = input() 4 | if name not in myPets: 5 | print('I do not have a pet named ' + name) 6 | else: 7 | print(name + ' is my pet.') 8 | -------------------------------------------------------------------------------- /15-time/README.md: -------------------------------------------------------------------------------- 1 | # time 2 |
 3 | import time
 4 | now = time.time()
 5 | 
6 | 7 | # datetime 8 | 1. import datetime 9 | 2. datetime.datetime.now() 10 | 3. datetime.datetime.fromtimestamp(time.time()) 11 | 4. datetime.timedelta() 12 | 13 | -------------------------------------------------------------------------------- /03-function/zeroDivide.py: -------------------------------------------------------------------------------- 1 | def spam(divideBy): 2 | return 42 / divideBy 3 | 4 | try: 5 | print(spam(2)) 6 | print(spam(12)) 7 | print(spam(0)) 8 | print(spam(1)) 9 | except ZeroDivisionError: 10 | print('Error: Invalid argument.') 11 | -------------------------------------------------------------------------------- /08-file/pprintDemo.py: -------------------------------------------------------------------------------- 1 | import pprint 2 | 3 | cats = [{'name': 'Zophie', 'desc': 'chubby'}, {'name': 'Pooka', 'desc': 'fluffy'}] 4 | pprint.pformat(cats) 5 | 6 | fileObj = open('myCats.py', 'w') 7 | fileObj.write('cats = ' + pprint.pformat(cats) + '\n') 8 | fileObj.close() -------------------------------------------------------------------------------- /13-pdf-word/readDocx.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | 3 | import docx 4 | 5 | def getText(filename): 6 | doc = docx.Document(filename) 7 | fullText = [] 8 | for para in doc.paragraphs: 9 | fullText.append(para.text) 10 | return '\n'.join(fullText) 11 | -------------------------------------------------------------------------------- /10-debug/buggyAddingProgram.py: -------------------------------------------------------------------------------- 1 | print('Enter the first number to add:') 2 | first = input() 3 | print('Enter the second number to add:') 4 | second = input() 5 | print('Enter the third number to add:') 6 | third = input() 7 | print('The sum is ' + first + second + third) 8 | -------------------------------------------------------------------------------- /15-time/threadDemo.py: -------------------------------------------------------------------------------- 1 | import threading, time 2 | print('Start of program.') 3 | 4 | def takeANap(): 5 | time.sleep(5) 6 | print('Wake up!') 7 | 8 | threadObj = threading.Thread(target=takeANap) 9 | threadObj.start() 10 | 11 | print('End of program.') 12 | -------------------------------------------------------------------------------- /18-GUI-control/moveRel.py: -------------------------------------------------------------------------------- 1 | import pyautogui 2 | 3 | for i in range(10): 4 | pyautogui.moveRel(100, 0, duration=0.25) 5 | pyautogui.moveRel(0, 100, duration=0.25) 6 | pyautogui.moveRel(-100, 0, duration=0.25) 7 | pyautogui.moveRel(0, -100, duration=0.25) 8 | -------------------------------------------------------------------------------- /18-GUI-control/moveTo.py: -------------------------------------------------------------------------------- 1 | import pyautogui 2 | 3 | for i in range(10): 4 | pyautogui.moveTo(100, 100, duration=0.25) 5 | pyautogui.moveTo(200, 100, duration=0.25) 6 | pyautogui.moveTo(200, 200, duration=0.25) 7 | pyautogui.moveTo(100, 200, duration=0.25) 8 | -------------------------------------------------------------------------------- /automate_online-materials/coinFlip.py: -------------------------------------------------------------------------------- 1 | import random 2 | heads = 0 3 | for i in range(1, 1001): 4 | if random.randint(0, 1) == 1: 5 | heads = heads + 1 6 | if i == 500: 7 | print('Halfway done!') 8 | print('Heads came up ' + str(heads) + ' times.') 9 | -------------------------------------------------------------------------------- /05-dict/characterCount.py: -------------------------------------------------------------------------------- 1 | message = 'It was a bright cold day in April, and the clocks were striking thirteen.' 2 | count = {} 3 | 4 | for character in message: 5 | #count.setdefault(character, 0) 6 | count[character] = count.get(character, 0) + 1 7 | 8 | print(count) 9 | -------------------------------------------------------------------------------- /13-pdf-word/addBreakToDocx.py: -------------------------------------------------------------------------------- 1 | import docx 2 | 3 | doc = docx.Document() 4 | doc.add_paragraph('This is on the first page!') 5 | doc.paragraphs[0].runs[0].add_break(docx.text.run.WD_BREAK.PAGE) 6 | doc.add_paragraph('This is on the second page!') 7 | 8 | doc.save('twoPage.docx') -------------------------------------------------------------------------------- /automate_online-materials/zeroDivide.py: -------------------------------------------------------------------------------- 1 | def spam(divideBy): 2 | return 42 / divideBy 3 | 4 | try: 5 | print(spam(2)) 6 | print(spam(12)) 7 | print(spam(0)) 8 | print(spam(1)) 9 | except ZeroDivisionError: 10 | print('Error: Invalid argument.') 11 | -------------------------------------------------------------------------------- /13-pdf-word/addHeaderToDocx.py: -------------------------------------------------------------------------------- 1 | import docx 2 | 3 | doc = docx.Document() 4 | doc.add_heading('Head 0', 0) 5 | doc.add_heading('Head 1', 1) 6 | doc.add_heading('Head 2', 2) 7 | doc.add_heading('Head 3', 3) 8 | doc.add_heading('Head 4', 4) 9 | 10 | doc.save('headings.docx') 11 | -------------------------------------------------------------------------------- /14-csv-json/jsonLoadsAndDumps.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | stringOfJsonData = '{"name": "Zophie", "isCat": true, "miceCaught": 0, "felineIQ": null}' 4 | jsonDataAsPythonValue = json.loads(stringOfJsonData) 5 | print(jsonDataAsPythonValue) 6 | print(json.dumps(jsonDataAsPythonValue)) 7 | 8 | -------------------------------------------------------------------------------- /18-GUI-control/commentAfterDelay.py: -------------------------------------------------------------------------------- 1 | import pyautogui 2 | import time 3 | def commentAfterDelay(): 4 | pyautogui.click(100, 100) 5 | pyautogui.typewrite('In IDLE, Alt-3 commets out a line.') 6 | time.sleep(2) 7 | pyautogui.hotkey('alt', '3') 8 | 9 | 10 | commentAfterDelay() -------------------------------------------------------------------------------- /automate_online-materials/readDocx.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | 3 | import docx 4 | 5 | def getText(filename): 6 | doc = docx.Document(filename) 7 | fullText = [] 8 | for para in doc.paragraphs: 9 | fullText.append(para.text) 10 | return '\n\n'.join(fullText) 11 | -------------------------------------------------------------------------------- /11-web/downloadAllLinks.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import bs4 3 | from selenium import webdriver 4 | 5 | # open browser 6 | browser = webdriver.Firefox() 7 | # open page 8 | browser.get(url) 9 | 10 | # get all links: bs4 11 | # download each link and test status code: requests 12 | -------------------------------------------------------------------------------- /automate_online-materials/buggyAddingProgram.py: -------------------------------------------------------------------------------- 1 | print('Enter the first number to add:') 2 | first = input() 3 | print('Enter the second number to add:') 4 | second = input() 5 | print('Enter the third number to add:') 6 | third = input() 7 | print('The sum is ' + first + second + third) 8 | -------------------------------------------------------------------------------- /automate_online-materials/characterCount.py: -------------------------------------------------------------------------------- 1 | message = 'It was a bright cold day in April, and the clocks were striking thirteen.' 2 | count = {} 3 | 4 | for character in message: 5 | count.setdefault(character, 0) 6 | count[character] = count[character] + 1 7 | 8 | print(count) 9 | -------------------------------------------------------------------------------- /automate_online-materials/threadDemo.py: -------------------------------------------------------------------------------- 1 | import threading, time 2 | print('Start of program.') 3 | 4 | def takeANap(): 5 | time.sleep(5) 6 | print('Wake up!') 7 | 8 | threadObj = threading.Thread(target=takeANap) 9 | threadObj.start() 10 | 11 | print('End of program.') 12 | -------------------------------------------------------------------------------- /automate_online-materials/getDocxText.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | 3 | import docx 4 | 5 | def getDocxText(filename): 6 | doc = docx.Document(filename) 7 | fullText = [] 8 | for para in doc.paragraphs: 9 | fullText.append(para.text) 10 | return '\n\n'.join(fullText) 11 | -------------------------------------------------------------------------------- /10-debug/format_exc.py: -------------------------------------------------------------------------------- 1 | import traceback 2 | try: 3 | raise Exception('This is the error message.') 4 | except: 5 | errorFile = open('errorInfo.txt', 'w') 6 | errorFile.write(traceback.format_exc()) 7 | errorFile.close() 8 | print('The traceback info was written to errorInfo.txt.') -------------------------------------------------------------------------------- /03-function/sameName3.py: -------------------------------------------------------------------------------- 1 | def spam(): 2 | global eggs # this is the global 3 | eggs = 'spam' 4 | 5 | def bacon(): 6 | eggs = 'bacon' # this is a local 7 | 8 | def ham(): 9 | print(eggs) # this is the global 10 | 11 | eggs = 42 # this is the global 12 | spam() 13 | print(eggs) 14 | -------------------------------------------------------------------------------- /11-web/bs4Demo.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import bs4 3 | 4 | exampleFile = open('example.html') 5 | exampleSoup = bs4.BeautifulSoup(exampleFile, 'html.parser') 6 | 7 | elems = exampleSoup.select('#author') 8 | print(elems[0].getText()) 9 | print(elems[0].get('id')) 10 | print(elems[0].attrs) 11 | -------------------------------------------------------------------------------- /automate_online-materials/vampire.py: -------------------------------------------------------------------------------- 1 | if name == 'Alice': 2 | print('Hi, Alice.') 3 | elif age < 12: 4 | print('You are not Alice, kiddo.') 5 | elif age > 2000: 6 | print('Unlike you, Alice is not an undead, immortal vampire.') 7 | elif age > 100: 8 | print('You are not Alice, grannie.') 9 | -------------------------------------------------------------------------------- /automate_online-materials/vampire2.py: -------------------------------------------------------------------------------- 1 | if name == 'Alice': 2 | print('Hi, Alice.') 3 | elif age < 12: 4 | print('You are not Alice, kiddo.') 5 | elif age > 100: 6 | print('You are not Alice, grannie.') 7 | elif age > 2000: 8 | print('Unlike you, Alice is not an undead, immortal vampire.') 9 | -------------------------------------------------------------------------------- /07-regex/stripRe.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | def stripRe(s): 4 | #stripRe = re.compile(r'^\s+\(.*\)\s+$') 5 | stripRegex = re.compile(r'^\s+(.*)\s+$') 6 | mo = stripRegex.search(s) 7 | return mo.group(1) 8 | 9 | 10 | strTest = ' hello world ' 11 | print(strTest) 12 | print(stripRe(strTest)) -------------------------------------------------------------------------------- /automate_online-materials/sameName3.py: -------------------------------------------------------------------------------- 1 | def spam(): 2 | global eggs # this is the global 3 | eggs = 'spam' 4 | 5 | def bacon(): 6 | eggs = 'bacon' # this is a local 7 | 8 | def ham(): 9 | print(eggs) # this is the global 10 | 11 | eggs = 42 # this is the global 12 | spam() 13 | print(eggs) 14 | -------------------------------------------------------------------------------- /05-dict/prettyCharacterCount.py: -------------------------------------------------------------------------------- 1 | import pprint 2 | message = 'It was a bright cold day in April, and the clocks were striking thirteen.' 3 | count = {} 4 | 5 | for character in message: 6 | #count.setdefault(character, 0) 7 | count[character] = count.get(character, 0) + 1 8 | 9 | pprint.pprint(count) 10 | -------------------------------------------------------------------------------- /12-excel/stylingUnit.py: -------------------------------------------------------------------------------- 1 | from openpyxl.styles import colors 2 | from openpyxl.styles import Font, Color 3 | from openpyxl import Workbook 4 | wb = Workbook() 5 | ws = wb.active 6 | sheet = wb.active 7 | ft = Font(size=24, italic=True) 8 | sheet['A1'].font = ft 9 | sheet['A1'] = '24 Italic' 10 | wb.save('styled.xlsx') 11 | -------------------------------------------------------------------------------- /automate_online-materials/prettyCharacterCount.py: -------------------------------------------------------------------------------- 1 | import pprint 2 | message = 'It was a bright cold day in April, and the clocks were striking thirteen.' 3 | count = {} 4 | 5 | for character in message: 6 | count.setdefault(character, 0) 7 | count[character] = count[character] + 1 8 | 9 | pprint.pprint(count) 10 | -------------------------------------------------------------------------------- /automate_online-materials/swordfish.py: -------------------------------------------------------------------------------- 1 | while True: 2 | print('Who are you?') 3 | name = input() 4 | if name != 'Joe': 5 | continue 6 | print('Hello, Joe. What is the password? (It is a fish.)') 7 | password = input() 8 | if password == 'swordfish': 9 | break 10 | print('Access granted.') -------------------------------------------------------------------------------- /08-file/shelfFile.py: -------------------------------------------------------------------------------- 1 | import shelve 2 | 3 | # save data to shelf file 4 | shelfFile = shelve.open('mydata') 5 | cats = ['Zophie', 'Pooka', 'Simon'] 6 | shelfFile['cats'] = cats 7 | shelfFile.close() 8 | 9 | # read data from shelf file 10 | shelfFile = shelve.open('mydata') 11 | print(shelfFile['cats']) 12 | shelfFile.close() 13 | -------------------------------------------------------------------------------- /03-function/sameName.py: -------------------------------------------------------------------------------- 1 | def spam(): 2 | eggs = 'spam local' 3 | print(eggs) # prints 'spam local' 4 | 5 | def bacon(): 6 | eggs = 'bacon local' 7 | print(eggs) # prints 'bacon local' 8 | spam() 9 | print(eggs) # prints 'bacon local' 10 | 11 | eggs = 'global' 12 | bacon() 13 | print(eggs) # prints 'global' 14 | -------------------------------------------------------------------------------- /11-web/downloadImages.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import bs4 3 | from selenium import webdriver 4 | 5 | # open browser 6 | browser = webdriver.Firefox() 7 | # open page 8 | browser.get(url) 9 | 10 | # get query box and send keys: selenium 11 | # submit: selenium 12 | # get images links: bs4 13 | # download images by request and save 14 | -------------------------------------------------------------------------------- /14-csv-json/writeCsv.py: -------------------------------------------------------------------------------- 1 | import csv 2 | 3 | outputFile = open('output.csv', 'w', newline='') 4 | outputWriter = csv.writer(outputFile) 5 | outputWriter.writerow(['spam', 'eggs', 'bacon', 'ham']) 6 | outputWriter.writerow(['Hello, world!', 'eggs', 'bacon', 'ham']) 7 | outputWriter.writerow([1, 2, 3.141592, 4]) 8 | 9 | outputFile.close() 10 | 11 | -------------------------------------------------------------------------------- /automate_online-materials/sameName.py: -------------------------------------------------------------------------------- 1 | def spam(): 2 | eggs = 'spam local' 3 | print(eggs) # prints 'spam local' 4 | 5 | def bacon(): 6 | eggs = 'bacon local' 7 | print(eggs) # prints 'bacon local' 8 | spam() 9 | print(eggs) # prints 'bacon local' 10 | 11 | eggs = 'global' 12 | bacon() 13 | print(eggs) # prints 'global' 14 | -------------------------------------------------------------------------------- /11-web/example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | The Website Title 4 | 5 |

Download my Python book from my website.

6 |

Learn Python the easy way!

7 |

By Al Sweigart

8 | -------------------------------------------------------------------------------- /15-time/calcProd.py: -------------------------------------------------------------------------------- 1 | import time 2 | startTime = time.time() 3 | # Calculate the product of the first 100,000 numbers. 4 | product = 1 5 | for i in range(1, 100000): 6 | product = product * i 7 | endTime = time.time() 8 | print('The result is %s digits long.' % (len(str(product)))) 9 | print('Took %s seconds to calculate.' % (endTime - startTime)) 10 | -------------------------------------------------------------------------------- /04-list/allMyCats2.py: -------------------------------------------------------------------------------- 1 | catNames = [] 2 | while True: 3 | print('Enter the name of cat ' + str(len(catNames) + 1) + ' (Or enter nothing to stop.):') 4 | name = input() 5 | if name == '': 6 | break 7 | catNames = catNames + [name] # list concatenation 8 | print('The cat names are:') 9 | for name in catNames: 10 | print(' ' + name) 11 | -------------------------------------------------------------------------------- /11-web/seleniumFindElement.py: -------------------------------------------------------------------------------- 1 | from selenium import webdriver 2 | 3 | browser = webdriver.Firefox() 4 | browser.get('http://inventwithpython.com') 5 | try: 6 | elem = browser.find_element_by_class_name('bookcover') 7 | print('Found <%s> element with that class name!' % (elem.tag_name)) 8 | except: 9 | print('Was not able to find an element with that name.') -------------------------------------------------------------------------------- /14-csv-json/delimiterCsv.py: -------------------------------------------------------------------------------- 1 | import csv 2 | 3 | csvFile = open('example.tsv', 'w', newline='') 4 | csvWriter = csv.writer(csvFile, delimiter='\t', lineterminator='\n\n') 5 | csvWriter.writerow(['apples', 'oranges', 'grapes']) 6 | csvWriter.writerow(['eggs', 'bacon', 'ham']) 7 | csvWriter.writerow(['spam', 'spam', 'spam', 'spam', 'spam', 'spam']) 8 | 9 | csvFile.close() -------------------------------------------------------------------------------- /15-time/countdown.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # countdown.py - A simple countdown script. 3 | 4 | import time, subprocess 5 | 6 | timeLeft = 10 7 | while timeLeft > 0: 8 | print(timeLeft, end='') 9 | time.sleep(1) 10 | timeLeft = timeLeft - 1 11 | 12 | # At the end of the countdown, play a sound file. 13 | subprocess.Popen(['start','alarm.wav'], shell=True) 14 | -------------------------------------------------------------------------------- /13-pdf-word/addContentToDocx.py: -------------------------------------------------------------------------------- 1 | import docx 2 | 3 | doc = docx.Document() 4 | doc.add_paragraph('Hello world!') 5 | 6 | paraObj1 = doc.add_paragraph('This is a second paragraph.') 7 | paraObj2 = doc.add_paragraph('This is a yet another paragraph.') 8 | paraObj1.add_run(' This text is being added to the second paragraph.') 9 | 10 | doc.save('multipleParagraphs.docx') -------------------------------------------------------------------------------- /automate_online-materials/example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | The Website Title 4 | 5 |

Download my Python book from my website.

6 |

Learn Python the easy way!

7 |

By Al Sweigart

8 | -------------------------------------------------------------------------------- /08-file/baconFile.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | baconFile = open('bacon.txt', 'w') 4 | baconFile.write('Hello world!\n') 5 | baconFile.close() 6 | 7 | baconFile = open('bacon.txt', 'a') 8 | baconFile.write('Bacon is not a vegetable.') 9 | baconFile.close() 10 | 11 | baconFile = open('bacon.txt') 12 | content = baconFile.read() 13 | baconFile.close() 14 | 15 | print(content) 16 | -------------------------------------------------------------------------------- /automate_online-materials/calcProd.py: -------------------------------------------------------------------------------- 1 | import time 2 | startTime = time.time() 3 | # Calculate the product of the first 100,000 numbers. 4 | product = 1 5 | for i in range(1, 100000): 6 | product = product * i 7 | endTime = time.time() 8 | print('The result is %s digits long.' % (len(str(product)))) 9 | print('Took %s seconds to calculate.' % (endTime - startTime)) 10 | -------------------------------------------------------------------------------- /04-list/magic8Ball2.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | messages = ['It is certain', 4 | 'It is decidedly so', 5 | 'Yes definitely', 6 | 'Reply hazy try again', 7 | 'Ask again later', 8 | 'Concentrate and ask again', 9 | 'My reply is no', 10 | 'Outlook not so good', 11 | 'Very doubtful'] 12 | 13 | print(messages[random.randint(0, len(messages) - 1)]) 14 | -------------------------------------------------------------------------------- /automate_online-materials/allMyCats2.py: -------------------------------------------------------------------------------- 1 | catNames = [] 2 | while True: 3 | print('Enter the name of cat ' + str(len(catNames) + 1) + ' (Or enter nothing to stop.):') 4 | name = input() 5 | if name == '': 6 | break 7 | catNames = catNames + [name] # list concatenation 8 | print('The cat names are:') 9 | for name in catNames: 10 | print(' ' + name) 11 | -------------------------------------------------------------------------------- /automate_online-materials/countdown.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # countdown.py - A simple countdown script. 3 | 4 | import time, subprocess 5 | 6 | timeLeft = 60 7 | while timeLeft > 0: 8 | print(timeLeft, end='') 9 | time.sleep(1) 10 | timeLeft = timeLeft - 1 11 | 12 | # At the end of the countdown, play a sound file. 13 | subprocess.Popen(['start','alarm.wav'], shell=True) 14 | -------------------------------------------------------------------------------- /06-str/picnicTable.py: -------------------------------------------------------------------------------- 1 | def printPicnic(itemsDict, leftWidth, rightWidth): 2 | print('PICNIC ITEMS'.center(leftWidth + rightWidth, '-')) 3 | for k, v in itemsDict.items(): 4 | print(k.ljust(leftWidth, '.') + str(v).rjust(rightWidth)) 5 | 6 | picnicItems = {'sandwiches': 4, 'apples': 12, 'cups': 4, 'cookies': 8000} 7 | printPicnic(picnicItems, 12, 5) 8 | printPicnic(picnicItems, 20, 6) 9 | -------------------------------------------------------------------------------- /automate_online-materials/magic8Ball2.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | messages = ['It is certain', 4 | 'It is decidedly so', 5 | 'Yes definitely', 6 | 'Reply hazy try again', 7 | 'Ask again later', 8 | 'Concentrate and ask again', 9 | 'My reply is no', 10 | 'Outlook not so good', 11 | 'Very doubtful'] 12 | 13 | print(messages[random.randint(0, len(messages) - 1)]) 14 | -------------------------------------------------------------------------------- /09-organize-file/traverseDir.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | for folderName, subfolders, filenames in os.walk('E:\\git\\AutomatePython'): 4 | print('The current folder is ' + folderName) 5 | 6 | for subfolder in subfolders: 7 | print('SUBFOLDER OF ' + folderName + ': ' + subfolder) 8 | for filename in filenames: 9 | print('FILE INSIDE ' + folderName + ': ' + filename) 10 | 11 | print() -------------------------------------------------------------------------------- /automate_online-materials/picnicTable.py: -------------------------------------------------------------------------------- 1 | def printPicnic(itemsDict, leftWidth, rightWidth): 2 | print('PICNIC ITEMS'.center(leftWidth + rightWidth, '-')) 3 | for k, v in itemsDict.items(): 4 | print(k.ljust(leftWidth, '.') + str(v).rjust(rightWidth)) 5 | 6 | picnicItems = {'sandwiches': 4, 'apples': 12, 'cups': 4, 'cookies': 8000} 7 | printPicnic(picnicItems, 12, 5) 8 | printPicnic(picnicItems, 20, 6) 9 | -------------------------------------------------------------------------------- /01-basic/hello.py: -------------------------------------------------------------------------------- 1 | # This program says hello and asks for my name. 2 | 3 | print('Hello world!') 4 | print('What is your name?') # ask for their name 5 | myName = input() 6 | print('It is good to meet you, ' + myName) 7 | print('The length of your name is:') 8 | print(len(myName)) 9 | print('What is your age?') # ask for their age 10 | myAge = input() 11 | print('You will be ' + str(int(myAge) + 1) + ' in a year.') 12 | -------------------------------------------------------------------------------- /03-function/collatz.py: -------------------------------------------------------------------------------- 1 | def collatz(number): 2 | if number % 2 == 0: 3 | number = number // 2 4 | else: 5 | number = 3 * number + 1 6 | print(number) 7 | return number 8 | 9 | try: 10 | number = int(input("Input a positive integer: ")) 11 | while number != 1: 12 | number = collatz(number) 13 | except ValueError: 14 | print("You should input a positive integer.") 15 | -------------------------------------------------------------------------------- /06-str/validateInput.py: -------------------------------------------------------------------------------- 1 | while True: 2 | print('Enter your age:') 3 | age = input() 4 | if age.isdecimal(): 5 | break 6 | print('Please enter a number for your age.') 7 | 8 | while True: 9 | print('Select a new password (letters and numbers only):') 10 | password = input() 11 | if password.isalnum(): 12 | break 13 | print('Passwords can only have letters and numbers.') 14 | -------------------------------------------------------------------------------- /13-pdf-word/rotatePdf.py: -------------------------------------------------------------------------------- 1 | import PyPDF2 2 | 3 | minutesFile = open('meetingminutes.pdf', 'rb') 4 | pdfReader = PyPDF2.PdfFileReader(minutesFile) 5 | page = pdfReader.getPage(0) 6 | page.rotateClockwise(90) 7 | 8 | pdfWriter =PyPDF2.PdfFileWriter() 9 | pdfWriter.addPage(page) 10 | resultPdfFile = open('rotatedPage.pdf', 'wb') 11 | pdfWriter.write(resultPdfFile) 12 | resultPdfFile.close() 13 | minutesFile.close() 14 | -------------------------------------------------------------------------------- /13-pdf-word/encryptPdf.py: -------------------------------------------------------------------------------- 1 | import PyPDF2 2 | 3 | pdfFile = open('meetingminutes.pdf', 'rb') 4 | pdfReader = PyPDF2.PdfFileReader(pdfFile) 5 | pdfWriter = PyPDF2.PdfFileWriter() 6 | 7 | for pageNum in range(pdfReader.numPages): 8 | pdfWriter.addPage(pdfReader.getPage(pageNum)) 9 | 10 | pdfWriter.encrypt('aforethought') 11 | resultPdf = open('encryptTest.pdf', 'wb') 12 | pdfWriter.write(resultPdf) 13 | resultPdf.close() 14 | -------------------------------------------------------------------------------- /automate_online-materials/inventory.py: -------------------------------------------------------------------------------- 1 | # inventory.py 2 | stuff = {'rope': 1, 'torch': 6, 'gold coin': 42, 'dagger': 1, 'arrow': 12} 3 | 4 | def display_inventory(inventory): 5 | print("Inventory:") 6 | item_total = 0 7 | for k, v in inventory.items(): 8 | print(str(v) + ' ' + k) 9 | item_total += v 10 | print("Total number of items: " + str(item_total)) 11 | 12 | display_inventory(stuff) 13 | -------------------------------------------------------------------------------- /05-dict/inventory.py: -------------------------------------------------------------------------------- 1 | # inventory.py 2 | stuff = {'rope': 1, 'torch': 6, 'gold coin': 42, 'dagger': 1, 'arrow': 12} 3 | 4 | def display_inventory(inventory): 5 | print("Inventory:") 6 | item_total = 0 7 | for k, v in inventory.items(): 8 | print(str(v) + '\t' + k) 9 | item_total += v 10 | print('-'*40) 11 | print("Total number of items: " + str(item_total)) 12 | 13 | display_inventory(stuff) 14 | -------------------------------------------------------------------------------- /13-pdf-word/README.md: -------------------------------------------------------------------------------- 1 | # PDF文档 2 | `pip install PyPDF2` 3 |
 4 |  import PyPDF2
 5 |  
6 | 7 | # Word文档 8 | ## 安装 9 | `pip install python-docx` 10 | 11 | ## Word文档简介 12 | * Document:表示整个文档 13 | * Paragraph:表示段落 14 | * Run:表示相同样式文本 15 | 16 | ## 使用 17 | `import docx 18 | doc = docx.Document(filename)` 19 | 20 | ## Word样式 21 | * 段落样式:可以应用于Paragraph 22 | * 字符样式:可以应用于Run对象 23 | * 链接样式:可以应用于Paragraph和Run对象 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /automate_online-materials/hello.py: -------------------------------------------------------------------------------- 1 | # This program says hello and asks for my name. 2 | 3 | print('Hello world!') 4 | print('What is your name?') # ask for their name 5 | myName = input() 6 | print('It is good to meet you, ' + myName) 7 | print('The length of your name is:') 8 | print(len(myName)) 9 | print('What is your age?') # ask for their age 10 | myAge = input() 11 | print('You will be ' + str(int(myAge) + 1) + ' in a year.') 12 | -------------------------------------------------------------------------------- /11-web/mapIt.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # mapIt.py - Launches a map in the browser using an address from the 3 | # command line or clipboard. 4 | 5 | import webbrowser, sys, pyperclip 6 | 7 | if len(sys.argv) > 1: 8 | # Get address from command line. 9 | address = ' '.join(sys.argv[1:]) 10 | else: 11 | # Get address from clipboard. 12 | address = pyperclip.paste() 13 | 14 | webbrowser.open('https://cn.bing.com/ditu/Default.aspx?q=' + address) 15 | -------------------------------------------------------------------------------- /13-pdf-word/decryptPdfWithDict.py: -------------------------------------------------------------------------------- 1 | import PyPDF2 2 | 3 | # load PDF 4 | pdfFile = open('encryptTest.pdf', 'rb') 5 | pdfReader = PyPDF2.PdfFileReader(pdfFile) 6 | 7 | # loop dict list and try to decrypt the pdf file 8 | with open('dictionary.txt') as f: 9 | for word in f: 10 | word = word.strip().lower() 11 | # if success, print the password 12 | if pdfReader.decrypt(word): 13 | print(word) 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /automate_online-materials/validateInput.py: -------------------------------------------------------------------------------- 1 | while True: 2 | print('Enter your age:') 3 | age = input() 4 | if age.isdecimal(): 5 | break 6 | print('Please enter a number for your age.') 7 | 8 | while True: 9 | print('Select a new password (letters and numbers only):') 10 | password = input() 11 | if password.isalnum(): 12 | break 13 | print('Passwords can only have letters and numbers.') -------------------------------------------------------------------------------- /06-str/bulletPointAdder.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # Adds Wikipedia bullet points to the start 3 | # of each line of text on the clipboard. 4 | 5 | import pyperclip 6 | text = pyperclip.paste() 7 | 8 | #Separate lines and add stars. 9 | lines = text.split('\n') 10 | for i in range(len(lines)): # loop through all indexes for "lines" list 11 | lines[i] = '* ' + lines[i] # add star to each string in "lines" list 12 | text = '\n'.join(lines) 13 | pyperclip.copy(text) 14 | -------------------------------------------------------------------------------- /10-debug/myProgramLog.txt: -------------------------------------------------------------------------------- 1 | 2017-07-02 20:28:30,480 - DEBUG - Start of program 2 | 2017-07-02 20:28:30,480 - DEBUG - Start of factorial(5%) 3 | 2017-07-02 20:28:30,480 - DEBUG - i is 1, total is 1 4 | 2017-07-02 20:28:30,480 - DEBUG - i is 2, total is 2 5 | 2017-07-02 20:28:30,480 - DEBUG - i is 3, total is 6 6 | 2017-07-02 20:28:30,480 - DEBUG - i is 4, total is 24 7 | 2017-07-02 20:28:30,480 - DEBUG - i is 5, total is 120 8 | 2017-07-02 20:28:30,480 - DEBUG - End of program 9 | -------------------------------------------------------------------------------- /automate_online-materials/mapIt.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # mapIt.py - Launches a map in the browser using an address from the 3 | # command line or clipboard. 4 | 5 | import webbrowser, sys, pyperclip 6 | 7 | if len(sys.argv) > 1: 8 | # Get address from command line. 9 | address = ' '.join(sys.argv[1:]) 10 | else: 11 | # Get address from clipboard. 12 | address = pyperclip.paste() 13 | 14 | webbrowser.open('https://www.google.com/maps/place/' + address) 15 | -------------------------------------------------------------------------------- /11-web/seleniumLoginGithub.py: -------------------------------------------------------------------------------- 1 | from selenium import webdriver 2 | 3 | account = 'your_account' 4 | pwd = 'your_password' 5 | 6 | browser = webdriver.Firefox() 7 | browser.get('https://github.com') 8 | loginElem = browser.find_element_by_link_text('Sign in') 9 | loginElem.click() 10 | emailElem = browser.find_element_by_id('login_field') 11 | emailElem.send_keys(account) 12 | pwdElem = browser.find_element_by_id('password') 13 | pwdElem.send_keys(pwd) 14 | pwdElem.submit() -------------------------------------------------------------------------------- /09-organize-file/zipfileDemo.py: -------------------------------------------------------------------------------- 1 | import os 2 | import zipfile 3 | 4 | os.chdir('E:\\') 5 | exampleZip = zipfile.ZipFile('mupdf-1.9a-windows.zip') 6 | print(exampleZip.namelist()) 7 | 8 | spamInfo = exampleZip.getinfo('mupdf-1.9a-windows/COPYING.txt') 9 | print(spamInfo.file_size) 10 | print(spamInfo.compress_size) 11 | 12 | print('Compressed file is %sx smaller!', (round(spamInfo.file_size/spamInfo.compress_size, 2))) 13 | # exampleZip.extractall() 14 | exampleZip.close() 15 | -------------------------------------------------------------------------------- /18-GUI-control/spiralDraw.py: -------------------------------------------------------------------------------- 1 | import pyautogui 2 | import time 3 | 4 | time.sleep(5) 5 | pyautogui.click() 6 | distance = 200 7 | dur = 0.01 8 | 9 | while distance > 0: 10 | pyautogui.dragRel(distance, 0, duration=dur) # move right 11 | distance -= 5 12 | pyautogui.dragRel(0, distance, duration=dur) # move down 13 | pyautogui.dragRel(-distance, 0, duration=dur) # move left 14 | distance -= 5 15 | pyautogui.dragRel(0, -distance, duration=dur) # move up -------------------------------------------------------------------------------- /automate_online-materials/bulletPointAdder.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # Adds Wikipedia bullet points to the start 3 | # of each line of text on the clipboard. 4 | 5 | import pyperclip 6 | text = pyperclip.paste() 7 | 8 | #Separate lines and add stars. 9 | lines = text.split('\n') 10 | for i in range(len(lines)): # loop through all indexes for "lines" list 11 | lines[i] = '* ' + lines[i] # add star to each string in "lines" list 12 | text = '\n'.join(lines) 13 | pyperclip.copy(text) 14 | -------------------------------------------------------------------------------- /12-excel/readExcel.py: -------------------------------------------------------------------------------- 1 | import openpyxl 2 | 3 | wb = openpyxl.load_workbook('example.xlsx') 4 | sheet = wb.get_sheet_by_name('Sheet1') 5 | print(sheet.cell(row=1, column=2).value) 6 | 7 | for i in range(1, 8, 2): 8 | print(i, sheet.cell(row=i, column=2).value) 9 | 10 | print(sheet.max_row, sheet.max_column) 11 | 12 | for rowOfCellObjs in sheet['A1':'C3']: 13 | for cellObj in rowOfCellObjs: 14 | print(cellObj.coordinate, cellObj.value) 15 | print('--- END OF ROW ---') -------------------------------------------------------------------------------- /11-web/requestsDemo.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | res = requests.get('http://www.gutenberg.org/cache/epub/1112/pg1112.txt') 4 | #res = requests.get('http://inventwithpython.com/page_that_does_not_exist') 5 | try: 6 | res.raise_for_status() 7 | playFile = open('RemeoAndJuliet.txt', 'wb') 8 | for chunk in res.iter_content(100000): 9 | playFile.write(chunk) 10 | playFile.close() 11 | except Exception as exc: 12 | print('There was a problem: %s' % (exc)) 13 | 14 | -------------------------------------------------------------------------------- /11-web/play2048.py: -------------------------------------------------------------------------------- 1 | from selenium import webdriver 2 | from selenium.webdriver.common.keys import Keys 3 | browser = webdriver.Firefox() 4 | browser.get('https://gabrielecirulli.github.io/2048') 5 | htmlElem = browser.find_element_by_tag_name('html') 6 | 7 | while True: 8 | htmlElem.send_keys(Keys.DOWN) # scrolls to bottom 9 | htmlElem.send_keys(Keys.RIGHT) # scrolls to top 10 | htmlElem.send_keys(Keys.UP) # scrolls to bottom 11 | htmlElem.send_keys(Keys.LEFT) # scrolls to bottom 12 | -------------------------------------------------------------------------------- /08-file/madlibs.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | text = "The ADJECTIVE panda walked to the NOUN and then VERB. A nearby NOUN was unaffected by these events." 4 | 5 | regex = '[A-Z]{2,}' 6 | wordsRegex = re.compile(regex) 7 | 8 | while True: 9 | mo = wordsRegex.search(text) 10 | if mo == None: 11 | #print('No words to be replaced.') 12 | break 13 | word = input('Enter an ' + mo.group().lower() + ':\n') 14 | text = wordsRegex.sub(' '+word, text, count=1) 15 | 16 | print(text) 17 | -------------------------------------------------------------------------------- /12-excel/README.md: -------------------------------------------------------------------------------- 1 | # openpyxl模块:处理Excel表格 2 | `pip install openpyxl` 3 |
 4 | import openpyxl
 5 | wb = openpyxl.load_workbook('example.xlsx')
 6 | sheet = wb.get_sheet_by_name('Sheet1')
 7 | 
8 | 9 | # 从电子表格文件中读取单元格涉及的所有函数、方法和数据类型。 10 | 1. 导入 openpyxl 模块。 11 | 2. 调用 openpyxl.load_workbook()函数。 12 | 3. 取得 Workbook 对象。 13 | 4. 调用 get_active_sheet()或 get_sheet_by_name()工作簿方法。 14 | 5. 取得 Worksheet 对象。 15 | 6. 使用索引或工作表的 cell()方法,带上 row 和 column 关键字参数。 16 | 7. 取得 Cell 对象。 17 | 8. 读取 Cell 对象的 value 属性。 18 | -------------------------------------------------------------------------------- /18-GUI-control/README.md: -------------------------------------------------------------------------------- 1 | # pyautogui 2 | `pip install pyautogui` 3 |
 4 | import pyautogui
 5 | pyautogui.PAUSE = 1
 6 | pyautogui.FAILSAFE = True
 7 | 
8 | > Methods 9 |
10 | moveTo()
11 | moveRel()
12 | position()
13 | click()
14 | mouseDown()
15 | mouseUp()
16 | doubleClick()
17 | rightClick()
18 | middleClick()
19 | dragTo()
20 | dragRel()
21 | scroll()
22 | screenshot()
23 | pixelMathesColor()
24 | locateOnScreen()
25 | typewrite()
26 | keyDown()
27 | keyUp()
28 | hotkey('ctrl', 'c')
29 | 
30 | -------------------------------------------------------------------------------- /18-GUI-control/mouseNow.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # mouseNow.py - Displays the mouse cursor's current position. 3 | import pyautogui 4 | print('Press Ctrl-C to quit.') 5 | try: 6 | while True: 7 | # Get and print the mouse coordinates. 8 | x, y = pyautogui.position() 9 | positionStr = 'X: ' + str(x).rjust(4) + ' Y: ' + str(y).rjust(4) 10 | print(positionStr, end='') 11 | print('\b' * len(positionStr), end='', flush=True) 12 | 13 | except KeyboardInterrupt: 14 | print('\nDone.') 15 | -------------------------------------------------------------------------------- /04-list/allMyCats1.py: -------------------------------------------------------------------------------- 1 | print('Enter the name of cat 1:') 2 | catName1 = input() 3 | print('Enter the name of cat 2:') 4 | catName2 = input() 5 | print('Enter the name of cat 3:') 6 | catName3 = input() 7 | print('Enter the name of cat 4:') 8 | catName4 = input() 9 | print('Enter the name of cat 5:') 10 | catName5 = input() 11 | print('Enter the name of cat 6:') 12 | catName6 = input() 13 | print('The cat names are:') 14 | print(catName1 + ' ' + catName2 + ' ' + catName3 + ' ' + catName4 + ' ' + catName5 + ' ' + catName6) 15 | -------------------------------------------------------------------------------- /automate_online-materials/mouseNow.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # mouseNow.py - Displays the mouse cursor's current position. 3 | import pyautogui 4 | print('Press Ctrl-C to quit.') 5 | try: 6 | while True: 7 | # Get and print the mouse coordinates. 8 | x, y = pyautogui.position() 9 | positionStr = 'X: ' + str(x).rjust(4) + ' Y: ' + str(y).rjust(4) 10 | print(positionStr, end='') 11 | print('\b' * len(positionStr), end='', flush=True) 12 | 13 | except KeyboardInterrupt: 14 | print('\nDone.') 15 | -------------------------------------------------------------------------------- /automate_online-materials/allMyCats1.py: -------------------------------------------------------------------------------- 1 | print('Enter the name of cat 1:') 2 | catName1 = input() 3 | print('Enter the name of cat 2:') 4 | catName2 = input() 5 | print('Enter the name of cat 3:') 6 | catName3 = input() 7 | print('Enter the name of cat 4:') 8 | catName4 = input() 9 | print('Enter the name of cat 5:') 10 | catName5 = input() 11 | print('Enter the name of cat 6:') 12 | catName6 = input() 13 | print('The cat names are:') 14 | print(catName1 + ' ' + catName2 + ' ' + catName3 + ' ' + catName4 + ' ' + catName5 + ' ' + catName6) 15 | -------------------------------------------------------------------------------- /05-dict/birthdays.py: -------------------------------------------------------------------------------- 1 | birthdays = {'Alice': 'Apr 1', 'Bob': 'Dec 12', 'Carol': 'Mar 4'} 2 | 3 | while True: 4 | print('Enter a name: (blank to quit)') 5 | name = input() 6 | if name == '': 7 | break 8 | 9 | if name in birthdays: 10 | print(birthdays[name] + ' is the birthday of ' + name) 11 | else: 12 | print('I do not have birthday information for ' + name) 13 | print('What is their birthday?') 14 | bday = input() 15 | birthdays[name] = bday 16 | print('Birthday database updated.') 17 | -------------------------------------------------------------------------------- /automate_online-materials/factorialLog.py: -------------------------------------------------------------------------------- 1 | import logging 2 | logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s') 3 | logging.debug('Start of program') 4 | 5 | def factorial(n): 6 | logging.debug('Start of factorial(%s%%)' % (n)) 7 | total = 1 8 | for i in range(1, n + 1): 9 | total *= i 10 | logging.debug('i is ' + str(i) + ', total is ' + str(total)) 11 | return total 12 | logging.debug('End of factorial(%s%%)' % (n)) 13 | 14 | print(factorial(5)) 15 | logging.debug('End of program') -------------------------------------------------------------------------------- /16-email-sms/textMyself.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # textMyself.py - Defines the textmyself() function that texts a message 3 | # passed to it as a string. 4 | 5 | # Preset values: 6 | accountSID = 'ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' 7 | authToken = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' 8 | myNumber = '+15559998888' 9 | twilioNumber = '+15552225678' 10 | 11 | from twilio.rest import Client 12 | 13 | def textmyself(message): 14 | twilioCli = Client(accountSID, authToken) 15 | twilioCli.api.account.messages.create(body=message, from_=twilioNumber, to=myNumber) 16 | -------------------------------------------------------------------------------- /12-excel/excelToText.py: -------------------------------------------------------------------------------- 1 | import openpyxl 2 | import sys 3 | from openpyxl.utils.cell import get_column_letter 4 | 5 | # arguments validation 6 | textList = [] 7 | excelName = '' 8 | 9 | # create workbook 10 | wb = openpyxl.Workbook() 11 | sheet = wb.get_active_sheet() 12 | 13 | # open each file and save to workbook 14 | for i in range(1, sheet.max_column+1): 15 | with open(str(i)+'.txt', 'w') as f: 16 | for j in range(1, sheet.max_row+1): 17 | coord = get_column_letter(fileSeq) + str(rowSeq) 18 | f.write(sheet[coord].value) 19 | f.close() 20 | -------------------------------------------------------------------------------- /10-debug/carSim.py: -------------------------------------------------------------------------------- 1 | market_2nd = {'ns':'green', 'ew':'red'} 2 | mission_16th = {'ns':'yellow', 'ew':'green'} 3 | 4 | def switchLights(stoplight): 5 | assert 'red' in stoplight.values(), 'Neither light is red! ' + str(stoplight) 6 | for key in stoplight.keys(): 7 | if stoplight[key] == 'green': 8 | stoplight[key] = 'yellow' 9 | elif stoplight[key] == 'yellow': 10 | stoplight[key] = 'red' 11 | elif stoplight[key] == 'red': 12 | stoplight[key] = 'green' 13 | 14 | switchLights(market_2nd) 15 | switchLights(mission_16th) -------------------------------------------------------------------------------- /automate_online-materials/birthdays.py: -------------------------------------------------------------------------------- 1 | birthdays = {'Alice': 'Apr 1', 'Bob': 'Dec 12', 'Carol': 'Mar 4'} 2 | 3 | while True: 4 | print('Enter a name: (blank to quit)') 5 | name = input() 6 | if name == '': 7 | break 8 | 9 | if name in birthdays: 10 | print(birthdays[name] + ' is the birthday of ' + name) 11 | else: 12 | print('I do not have birthday information for ' + name) 13 | print('What is their birthday?') 14 | bday = input() 15 | birthdays[name] = bday 16 | print('Birthday database updated.') 17 | -------------------------------------------------------------------------------- /04-list/printGrid.py: -------------------------------------------------------------------------------- 1 | def printGrid(grid): 2 | for y in range(6): 3 | for x in range(9): 4 | print(grid[x][y], end='') 5 | print() 6 | 7 | grid = [['.', '.', '.', '.', '.', '.'], 8 | ['.', 'O', 'O', '.', '.', '.'], 9 | ['O', 'O', 'O', 'O', '.', '.'], 10 | ['O', 'O', 'O', 'O', 'O', '.'], 11 | ['.', 'O', 'O', 'O', 'O', 'O'], 12 | ['O', 'O', 'O', 'O', 'O', '.'], 13 | ['O', 'O', 'O', 'O', '.', '.'], 14 | ['.', 'O', 'O', '.', '.', '.'], 15 | ['.', '.', '.', '.', '.', '.']] 16 | printGrid(grid) 17 | -------------------------------------------------------------------------------- /automate_online-materials/textMyself.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # textMyself.py - Defines the textmyself() function that texts a message 3 | # passed to it as a string. 4 | 5 | # Preset values: 6 | accountSID = 'ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' 7 | authToken = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' 8 | myNumber = '+15559998888' 9 | twilioNumber = '+15552225678' 10 | 11 | from twilio.rest import TwilioRestClient 12 | 13 | def textmyself(message): 14 | twilioCli = TwilioRestClient(accountSID, authToken) 15 | twilioCli.messages.create(body=message, from_=twilioNumber, to=myNumber) 16 | -------------------------------------------------------------------------------- /10-debug/guessCoin.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | guess = '' 4 | ans = ('heads', 'tails') 5 | while guess not in ans: 6 | print('Guess the coin toss! Enter heads or tails:') 7 | guess = input() 8 | 9 | toss = ans[random.randint(0, 1)] 10 | if toss == guess: 11 | print('You got it!') 12 | else: 13 | print('Nope! Guess again! Enter heads or tails:') 14 | guess = input() 15 | toss = ans[random.randint(0, 1)] 16 | if toss == guess: 17 | print('You got it!') 18 | else: 19 | print('Nope. You are really bad at this game.') 20 | -------------------------------------------------------------------------------- /12-excel/textToExcel.py: -------------------------------------------------------------------------------- 1 | import openpyxl 2 | import sys 3 | from openpyxl.utils.cell import get_column_letter 4 | 5 | # arguments validation 6 | textList = [] 7 | excelName = '' 8 | 9 | # create workbook 10 | wb = openpyxl.Workbook() 11 | sheet = wb.get_active_sheet() 12 | 13 | # open each file and save to workbook 14 | fileSeq = 0 15 | for file in textList: 16 | fileSeq += 1 17 | with open(file) as f: 18 | rowSeq = 1 19 | for line in f.readlines(): 20 | coord = get_column_letter(fileSeq) + str(rowSeq) 21 | sheet[coord] = line 22 | 23 | # save workbook 24 | wb.save(excelName) 25 | -------------------------------------------------------------------------------- /automate_online-materials/lucky.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # lucky.py - Opens several Google search results. 3 | 4 | import requests, sys, webbrowser, bs4 5 | 6 | print('Googling...') # display text while downloading the Google page 7 | res = requests.get('http://google.com/search?q=' + ' '.join(sys.argv[1:])) 8 | res.raise_for_status() 9 | 10 | # Retrieve top search result links. 11 | soup = bs4.BeautifulSoup(res.text) 12 | 13 | # Open a browser tab for each result. 14 | linkElems = soup.select('.r a') 15 | numOpen = min(5, len(linkElems)) 16 | for i in range(numOpen): 17 | webbrowser.open('http://google.com' + linkElems[i].get('href')) 18 | -------------------------------------------------------------------------------- /09-organize-file/filesize.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | 4 | def search(dir, size): 5 | # dir exists 6 | if not os.path.exists(dir): 7 | print('Directory ' + dir + ' not exists.') 8 | 9 | # list all files in dir 10 | for dirpath, dirnames, filenames in os.walk(dir): 11 | for filename in filenames: 12 | filepath = os.path.join(dirpath, filename) 13 | filesize = os.path.getsize(filepath) 14 | if filesize > size: 15 | print(str(filesize).ljust(16), filepath) 16 | # if filesize is bigger than size, print it's path 17 | 18 | search('E:\\', 1024*1024*1024) -------------------------------------------------------------------------------- /05-dict/dragonLoot.py: -------------------------------------------------------------------------------- 1 | def displayInventory(inventory): 2 | print("Inventory:") 3 | item_total = 0 4 | for k, v in inventory.items(): 5 | print(str(v) + '\t' + k) 6 | item_total += v 7 | print('-'*40) 8 | print("Total number of items: " + str(item_total)) 9 | 10 | def addToInventory(inventory, addedItems): 11 | for item in addedItems: 12 | inventory[item] = inventory.get(item, 0) + 1 13 | return inventory 14 | 15 | inv = {'gold coin': 42, 'rope': 1} 16 | dragonLoot = ['gold coin', 'dagger', 'gold coin', 'gold coin', 'ruby'] 17 | inv = addToInventory(inv, dragonLoot) 18 | displayInventory(inv) 19 | -------------------------------------------------------------------------------- /11-web/lucky.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # lucky.py - Opens several Google search results. 3 | 4 | import requests, sys, webbrowser, bs4 5 | 6 | print('Baiduing...') # display text while downloading the Google page 7 | res = requests.get('http://www.baidu.com/s?wd=' + ' '.join(sys.argv[1:])) 8 | res.raise_for_status() 9 | 10 | # Retrieve top search result links. 11 | soup = bs4.BeautifulSoup(res.text, 'html.parser') 12 | 13 | # Open a browser tab for each result. 14 | linkElems = soup.select('h3 a') 15 | numOpen = min(5, len(linkElems)) 16 | for i in range(numOpen): 17 | #print(linkElems[i].get('href')) 18 | webbrowser.open(linkElems[i].get('href')) 19 | -------------------------------------------------------------------------------- /06-str/pw.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # pw.py - An insecure password locker program. 3 | 4 | PASSWORDS = {'email': 'F7minlBDDuvMJuxESSKHFhTxFtjVB6', 5 | 'blog': 'VmALvQyKAxiVH5G8v01if1MLZF3sdt', 6 | 'luggage': '12345'} 7 | 8 | import sys, pyperclip 9 | if len(sys.argv) < 2: 10 | print('Usage: py pw.py [account] - copy account password') 11 | sys.exit() 12 | 13 | account = sys.argv[1] # first command line arg is the account name 14 | 15 | if account in PASSWORDS: 16 | pyperclip.copy(PASSWORDS[account]) 17 | print('Password for ' + account + ' copied to clipboard.') 18 | else: 19 | print('There is no account named ' + account) 20 | -------------------------------------------------------------------------------- /07-regex/passwordValidation.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | def passwordValidation(pwd): 4 | if(len(pwd) < 8): 5 | return False 6 | upperRegex = re.compile(r'[A-Z]') 7 | lowerRegex = re.compile(r'[a-z]') 8 | numberRegex = re.compile(r'[0-9]') 9 | 10 | if upperRegex.search(pwd) and lowerRegex.search(pwd) and numberRegex.search(pwd): 11 | return True 12 | else: 13 | return False 14 | 15 | def printResult(pwd): 16 | print(pwd.ljust(20), passwordValidation(pwd)) 17 | 18 | 19 | printResult('HelloWorld123') 20 | printResult('HelloWorld') 21 | printResult('Hello123') 22 | printResult('H') 23 | printResult('elloorld123') 24 | printResult('HW123') -------------------------------------------------------------------------------- /automate_online-materials/pw.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # pw.py - An insecure password locker program. 3 | 4 | PASSWORDS = {'email': 'F7minlBDDuvMJuxESSKHFhTxFtjVB6', 5 | 'blog': 'VmALvQyKAxiVH5G8v01if1MLZF3sdt', 6 | 'luggage': '12345'} 7 | 8 | import sys, pyperclip 9 | if len(sys.argv) < 2: 10 | print('Usage: py pw.py [account] - copy account password') 11 | sys.exit() 12 | 13 | account = sys.argv[1] # first command line arg is the account name 14 | 15 | if account in PASSWORDS: 16 | pyperclip.copy(PASSWORDS[account]) 17 | print('Password for ' + account + ' copied to clipboard.') 18 | else: 19 | print('There is no account named ' + account) 20 | -------------------------------------------------------------------------------- /07-regex/readme.md: -------------------------------------------------------------------------------- 1 | 虽然在 Python 中使用正则表达式有几个步骤,但每一步都相当简单。 2 | 1. 用 import re 导入正则表达式模块。 3 | import re 4 | 2.用 re.compile()函数创建一个 Regex 对象(记得使用原始字符串)。 5 | regexObj = re.compile(r'\d{3}-\d{3}-\d{4}') 6 | 3.向 Regex 对象的 search()方法传入想查找的字符串。它返回一个 Match 对象。 7 | mo = regexObj.search(strObj) 8 | 4.调用 Match 对象的 group()方法,返回实际匹配文本的字符串。 9 | mo.group() 10 | 11 | regex test site: 12 | http://www.regexpal.com/ 13 | 14 | 花括号的“非贪心” 版本匹配尽可能最短的字符串,即在结束的花括号后跟着一个问号。 15 | 16 | \d 0 到 9 的任何数字 17 | \D 除 0 到 9 的数字以外的任何字符 18 | \w 任何字母、数字或下划线字符(可以认为是匹配“单词”字符) 19 | \W 除字母、数字和下划线以外的任何字符 20 | \s 空格、制表符或换行符(可以认为是匹配“空白”字符) 21 | \S 除空格、制表符和换行符以外的任何字符 22 | 23 | 24 | 通过传入 re.DOTALL 作为 re.compile()的第二个参数, 可以让句点字符匹配所有字符, 包括换行字符。 -------------------------------------------------------------------------------- /10-debug/boxPrint.py: -------------------------------------------------------------------------------- 1 | def boxPrint(symbol, width, height): 2 | if len(symbol) != 1: 3 | raise Exception('Symbol must be a single character string.') 4 | if width <= 2: 5 | raise Exception('Width must be greater than 2.') 6 | if height <= 2: 7 | raise Exception('Height must be greater than 2.') 8 | 9 | print(symbol * width) 10 | for i in range(height - 2): 11 | print(symbol + (' ' * (width - 2)) + symbol) 12 | print(symbol * width) 13 | 14 | for sym, w, h in (('*', 4, 4), ('O', 20, 5), ('x', 1, 3), ('ZZ', 3, 3)): 15 | try: 16 | boxPrint(sym, w, h) 17 | except Exception as err: 18 | print('An exception happened: ' + str(err)) 19 | -------------------------------------------------------------------------------- /10-debug/factorialLog.py: -------------------------------------------------------------------------------- 1 | import logging 2 | # logging.disable(logging.CRITICAL) 3 | #logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s') 4 | logging.basicConfig(filename='myProgramLog.txt', level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s') 5 | logging.debug('Start of program') 6 | 7 | def factorial(n): 8 | logging.debug('Start of factorial(%s%%)' % (n)) 9 | total = 1 10 | for i in range(1, n + 1): 11 | total *= i 12 | logging.debug('i is ' + str(i) + ', total is ' + str(total)) 13 | return total 14 | logging.debug('End of factorial(%s%%)' % (n)) 15 | 16 | print(factorial(5)) 17 | logging.debug('End of program') -------------------------------------------------------------------------------- /12-excel/multiplicationTable.py: -------------------------------------------------------------------------------- 1 | import openpyxl 2 | import sys 3 | from openpyxl.utils.cell import get_column_letter 4 | 5 | if len(sys.argv) < 2: 6 | print('usage: py multiplicationTable.py [NUM]') 7 | exit() 8 | num = int(sys.argv[1]) 9 | 10 | wb = openpyxl.Workbook() 11 | sheet = wb.get_active_sheet() 12 | 13 | for i in range(1, num+1): 14 | # fill the first row 15 | sheet[get_column_letter(i+1)+'1'] = i 16 | # fill the first column 17 | sheet['A'+str(i+1)] = i 18 | 19 | # fill the table 20 | for i in range(1, num+1): 21 | for j in range(1, num+1): 22 | sheet[get_column_letter(j+1)+str(i+1)] = i*j 23 | 24 | wb.save('multiplicationTable-'+str(num)+'.xlsx') 25 | -------------------------------------------------------------------------------- /13-pdf-word/docxDemo.py: -------------------------------------------------------------------------------- 1 | import docx 2 | 3 | doc = docx.Document('demo.docx') 4 | print(len(doc.paragraphs)) 5 | ''' 6 | 7 7 | ''' 8 | 9 | for p in doc.paragraphs: 10 | print(str(len(p.text)).ljust(8), p.text) 11 | 12 | ''' 13 | 14 Document Title 14 | 48 A plain paragraph with some bold and some italic 15 | 16 Heading, level 1 16 | 13 Intense quote 17 | 28 first item in unordered list 18 | 26 first item in ordered list 19 | 1 20 | ''' 21 | 22 | for r in doc.paragraphs[1].runs: 23 | print(str(len(r.text)).ljust(8), r.text) 24 | 25 | ''' 26 | 22 A plain paragraph with 27 | 6 some 28 | 4 bold 29 | 10 and some 30 | 6 italic 31 | ''' -------------------------------------------------------------------------------- /13-pdf-word/mergePdf.py: -------------------------------------------------------------------------------- 1 | import PyPDF2 2 | 3 | pdf1File = open('meetingminutes.pdf', 'rb') 4 | pdf2File = open('meetingminutes2.pdf', 'rb') 5 | pdf1Reader = PyPDF2.PdfFileReader(pdf1File) 6 | pdf2Reader = PyPDF2.PdfFileReader(pdf2File) 7 | pdfWriter = PyPDF2.PdfFileWriter() 8 | 9 | for pageNum in range(pdf1Reader.numPages): 10 | pageObj = pdf1Reader.getPage(pageNum) 11 | pdfWriter.addPage(pageObj) 12 | 13 | for pageNum in range(pdf2Reader.numPages): 14 | pageObj = pdf2Reader.getPage(pageNum) 15 | pdfWriter.addPage(pageObj) 16 | 17 | pdfOutputFile = open('combineminutes.pdf', 'wb') 18 | pdfWriter.write(pdfOutputFile) 19 | pdfOutputFile.close() 20 | pdf1File.close() 21 | pdf2File.close() 22 | -------------------------------------------------------------------------------- /11-web/sendEmailByCommandLine.py: -------------------------------------------------------------------------------- 1 | 2 | from selenium import webdriver 3 | 4 | account = 'your_account' 5 | pwd = 'your_password' 6 | 7 | # open browser 8 | browser = webdriver.Firefox() 9 | # open page 10 | browser.get('https://github.com') 11 | 12 | # login: get email and pwd element and send keys 13 | loginElem = browser.find_element_by_link_text('Sign in') 14 | loginElem.click() 15 | emailElem = browser.find_element_by_id('login_field') 16 | emailElem.send_keys(account) 17 | pwdElem = browser.find_element_by_id('password') 18 | pwdElem.send_keys(pwd) 19 | pwdElem.submit() 20 | # click create email button 21 | # get recevier element and send keys 22 | # get content element and send keys 23 | # get send button and submit -------------------------------------------------------------------------------- /13-pdf-word/watermarkPdf.py: -------------------------------------------------------------------------------- 1 | import PyPDF2 2 | 3 | minutesFile = open('meetingminutes.pdf', 'rb') 4 | pdfReader = PyPDF2.PdfFileReader(minutesFile) 5 | minutesFirstPage = pdfReader.getPage(0) 6 | 7 | 8 | pdfWatermarkReader = PyPDF2.PdfFileReader(open('watermark.pdf', 'rb')) 9 | minutesFirstPage.mergePage(pdfWatermarkReader.getPage(0)) 10 | 11 | pdfWriter = PyPDF2.PdfFileWriter() 12 | pdfWriter.addPage(minutesFirstPage) 13 | 14 | for pageNum in range(1, pdfReader.numPages): 15 | pageObj = pdfReader.getPage(pageNum) 16 | pdfWriter.addPage(pageObj) 17 | 18 | resultPdfFile = open('watermarkedCover.pdf', 'wb') 19 | pdfWriter.write(resultPdfFile) 20 | 21 | minutesFile.close() 22 | resultPdfFile.close() 23 | 24 | -------------------------------------------------------------------------------- /automate_online-materials/boxPrint.py: -------------------------------------------------------------------------------- 1 | def boxPrint(symbol, width, height): 2 | if len(symbol) != 1: 3 | raise Exception('Symbol must be a single character string.') 4 | if width <= 2: 5 | raise Exception('Width must be greater than 2.') 6 | if height <= 2: 7 | raise Exception('Height must be greater than 2.') 8 | 9 | print(symbol * width) 10 | for i in range(height - 2): 11 | print(symbol + (' ' * (width - 2)) + symbol) 12 | print(symbol * width) 13 | 14 | for sym, w, h in (('*', 4, 4), ('O', 20, 5), ('x', 1, 3), ('ZZ', 3, 3)): 15 | try: 16 | boxPrint(sym, w, h) 17 | except Exception as err: 18 | print('An exception happened: ' + str(err)) 19 | -------------------------------------------------------------------------------- /10-debug/README.md: -------------------------------------------------------------------------------- 1 | # raise 2 |
raise Exception(msg)
3 | 4 | # try...except...as... 5 |
try:
 6 |     code block
 7 | except Exception as err:
 8 |     error handling
9 | 10 | # traceback.format_exc() 11 | * convert traceback stack info to be a string 12 | 13 | # assert condition, message 14 | * Python -O option will disable assertions 15 | 16 | # logging module 17 |
18 | import logging
19 | logging.disable(logging.CRITICAL)
20 | logging.basicConfig(level=logging.DEBUG, format=' %(asctime)s - %(levelname)s - %(message)s')
21 | logging.basicConfig(filename='myProgramLog.txt', level=logging.DEBUG, 
22 |                     format='(asctime)s - %(levelname)s - %(message)s')
23 | logging.debug('Start of program')
24 | 
25 | -------------------------------------------------------------------------------- /12-excel/updateProduce.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # updateProduce.py - Corrects costs in produce sales spreadsheet. 3 | 4 | import openpyxl 5 | 6 | wb = openpyxl.load_workbook('produceSales.xlsx') 7 | sheet = wb.get_sheet_by_name('Sheet') 8 | 9 | # The produce types and their updated prices 10 | PRICE_UPDATES = {'Garlic': 3.07, 11 | 'Celery': 1.19, 12 | 'Lemon': 1.27} 13 | 14 | # Loop through the rows and update the prices. 15 | for rowNum in range(2, sheet.max_row): # skip the first row 16 | produceName = sheet.cell(row=rowNum, column=1).value 17 | if produceName in PRICE_UPDATES: 18 | sheet.cell(row=rowNum, column=2).value = PRICE_UPDATES[produceName] 19 | 20 | wb.save('updatedProduceSales.xlsx') 21 | 22 | -------------------------------------------------------------------------------- /08-file/find.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | import sys 4 | 5 | 6 | def getTxtFile(directory): 7 | txts = [] 8 | txtSuffix = r'\.txt$' 9 | txtRegex = re.compile(txtSuffix) 10 | for filename in os.listdir(directory): 11 | mo = txtRegex.search(filename) 12 | if mo: 13 | txts.append(filename) 14 | return txts 15 | 16 | def find(query, directory): 17 | txts = getTxtFile(directory) 18 | print(txts) 19 | queryRegex = re.compile(query) 20 | for txt in txts: 21 | with open(txt) as f: 22 | for line in f: 23 | mo = queryRegex.search(line) 24 | if mo: 25 | print(txt.ljust(20) + ": " + line, end='') 26 | 27 | find("world", ".") 28 | -------------------------------------------------------------------------------- /03-function/guessTheNumber.py: -------------------------------------------------------------------------------- 1 | # This is a guess the number game. 2 | import random 3 | secretNumber = random.randint(1, 20) 4 | print('I am thinking of a number between 1 and 20.') 5 | 6 | # Ask the player to guess 6 times. 7 | for guessesTaken in range(1, 7): 8 | print('Take a guess.') 9 | guess = int(input()) 10 | 11 | if guess < secretNumber: 12 | print('Your guess is too low.') 13 | elif guess > secretNumber: 14 | print('Your guess is too high.') 15 | else: 16 | break # This condition is the correct guess! 17 | 18 | if guess == secretNumber: 19 | print('Good job! You guessed my number in ' + str(guessesTaken) + ' guesses!') 20 | else: 21 | print('Nope. The number I was thinking of was ' + str(secretNumber)) 22 | -------------------------------------------------------------------------------- /09-organize-file/copy.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import shutil 4 | 5 | def copy(suffix, src, dst): 6 | # Create dst directory 7 | if not os.path.exists(dst): 8 | os.mkdir(dst) 9 | 10 | # list all files 11 | try: 12 | for dirpath, dirnames, filenames in os.walk(src): 13 | #print(dirpath, dirnames, filenames) 14 | for filename in filenames: 15 | if filename.endswith('.'+suffix): 16 | print(os.path.join(dirpath, filename)) 17 | # copy files with pointed suffix to dst 18 | shutil.copy(os.path.join(dirpath, filename), dst) 19 | except shutil.SameFileError: 20 | print("Finished copying file.") 21 | 22 | copy('py', '.', 'pyfiles') -------------------------------------------------------------------------------- /automate_online-materials/updateProduce.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # updateProduce.py - Corrects costs in produce sales spreadsheet. 3 | 4 | import openpyxl 5 | 6 | wb = openpyxl.load_workbook('produceSales.xlsx') 7 | sheet = wb.get_sheet_by_name('Sheet') 8 | 9 | # The produce types and their updated prices 10 | PRICE_UPDATES = {'Garlic': 3.07, 11 | 'Celery': 1.19, 12 | 'Lemon': 1.27} 13 | 14 | # Loop through the rows and update the prices. 15 | for rowNum in range(2, sheet.get_highest_row()): # skip the first row 16 | produceName = sheet.cell(row=rowNum, column=1).value 17 | if produceName in PRICE_UPDATES: 18 | sheet.cell(row=rowNum, column=2).value = PRICE_UPDATES[produceName] 19 | 20 | wb.save('updatedProduceSales.xlsx') 21 | -------------------------------------------------------------------------------- /automate_online-materials/guessTheNumber.py: -------------------------------------------------------------------------------- 1 | # This is a guess the number game. 2 | import random 3 | secretNumber = random.randint(1, 20) 4 | print('I am thinking of a number between 1 and 20.') 5 | 6 | # Ask the player to guess 6 times. 7 | for guessesTaken in range(1, 7): 8 | print('Take a guess.') 9 | guess = int(input()) 10 | 11 | if guess < secretNumber: 12 | print('Your guess is too low.') 13 | elif guess > secretNumber: 14 | print('Your guess is too high.') 15 | else: 16 | break # This condition is the correct guess! 17 | 18 | if guess == secretNumber: 19 | print('Good job! You guessed my number in ' + str(guessesTaken) + ' guesses!') 20 | else: 21 | print('Nope. The number I was thinking of was ' + str(secretNumber)) 22 | -------------------------------------------------------------------------------- /18-GUI-control/mouseNow2.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # mouseNow.py - Displays the mouse cursor's current position. 3 | import pyautogui 4 | print('Press Ctrl-C to quit.') 5 | try: 6 | while True: 7 | # Get and print the mouse coordinates. 8 | x, y = pyautogui.position() 9 | positionStr = 'X: ' + str(x).rjust(4) + ' Y: ' + str(y).rjust(4) 10 | pixelColor = pyautogui.screenshot().getpixel((x, y)) 11 | positionStr += ' RGB: (' + str(pixelColor[0]).rjust(3) 12 | positionStr += ', ' + str(pixelColor[1]).rjust(3) 13 | positionStr += ', ' + str(pixelColor[2]).rjust(3) + ')' 14 | print(positionStr, end='') 15 | print('\b' * len(positionStr), end='', flush=True) 16 | 17 | except KeyboardInterrupt: 18 | print('\nDone.') 19 | -------------------------------------------------------------------------------- /05-dict/ticTacToe.py: -------------------------------------------------------------------------------- 1 | theBoard = {'top-L': ' ', 'top-M': ' ', 'top-R': ' ', 2 | 'mid-L': ' ', 'mid-M': ' ', 'mid-R': ' ', 3 | 'low-L': ' ', 'low-M': ' ', 'low-R': ' '} 4 | def printBoard(board): 5 | print(board['top-L'] + '|' + board['top-M'] + '|' + board['top-R']) 6 | print('-+-+-') 7 | print(board['mid-L'] + '|' + board['mid-M'] + '|' + board['mid-R']) 8 | print('-+-+-') 9 | print(board['low-L'] + '|' + board['low-M'] + '|' + board['low-R']) 10 | 11 | turn = 'X' 12 | for i in range(9): 13 | printBoard(theBoard) 14 | print('Turn for ' + turn + '. Move on which space?') 15 | move = input() 16 | theBoard[move] = turn 17 | if turn == 'X': 18 | turn = 'O' 19 | else: 20 | turn = 'X' 21 | printBoard(theBoard) 22 | -------------------------------------------------------------------------------- /13-pdf-word/createInvitation.py: -------------------------------------------------------------------------------- 1 | import docx 2 | 3 | # create a docment 4 | doc = docx.Document('guestTemplete.docx') 5 | paragraphNum = len(doc.paragraphs) 6 | guestDoc = docx.Document() 7 | 8 | # open guests.txt file 9 | with open('guests.txt') as f: 10 | for guest in f.readlines(): 11 | paraSeq = 0 12 | # add each guest to the document 13 | for p in doc.paragraphs: 14 | paraSeq += 1 15 | if paraSeq == 2: 16 | p.add_run(guest) 17 | if paraSeq == paragraphNum: 18 | p.runs[len(p.runs)-1].add_break(docx.text.run.WD_BREAK.PAGE) 19 | # set text and style 20 | guestDoc.add_paragraph(p.text, p.style) 21 | 22 | # save file 23 | guestDoc.save('guestsInvitaion.docx') -------------------------------------------------------------------------------- /automate_online-materials/mouseNow2.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # mouseNow.py - Displays the mouse cursor's current position. 3 | import pyautogui 4 | print('Press Ctrl-C to quit.') 5 | try: 6 | while True: 7 | # Get and print the mouse coordinates. 8 | x, y = pyautogui.position() 9 | positionStr = 'X: ' + str(x).rjust(4) + ' Y: ' + str(y).rjust(4) 10 | pixelColor = pyautogui.screenshot().getpixel((x, y)) 11 | positionStr += ' RGB: (' + str(pixelColor[0]).rjust(3) 12 | positionStr += ', ' + str(pixelColor[1]).rjust(3) 13 | positionStr += ', ' + str(pixelColor[2]).rjust(3) + ')' 14 | print(positionStr, end='') 15 | print('\b' * len(positionStr), end='', flush=True) 16 | 17 | except KeyboardInterrupt: 18 | print('\nDone.') 19 | -------------------------------------------------------------------------------- /03-function/magic8Ball.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | def getAnswer(answerNumber): 4 | if answerNumber == 1: 5 | return 'It is certain' 6 | elif answerNumber == 2: 7 | return 'It is decidely decidedly so' 8 | elif answerNumber == 3: 9 | return 'Yes' 10 | elif answerNumber == 4: 11 | return 'Reply hazy try again' 12 | elif answerNumber == 5: 13 | return 'Ask again later' 14 | elif answerNumber == 6: 15 | return 'Concentrate and ask again' 16 | elif answerNumber == 7: 17 | return 'My reply is no' 18 | elif answerNumber == 8: 19 | return 'Outlook not so good' 20 | elif answerNumber == 9: 21 | return 'Very doubtful' 22 | 23 | r = random.randint(1, 9) 24 | fortune = getAnswer(r) 25 | print(fortune) 26 | -------------------------------------------------------------------------------- /automate_online-materials/magic8Ball.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | def getAnswer(answerNumber): 4 | if answerNumber == 1: 5 | return 'It is certain' 6 | elif answerNumber == 2: 7 | return 'It is decidely decidedly so' 8 | elif answerNumber == 3: 9 | return 'Yes' 10 | elif answerNumber == 4: 11 | return 'Reply hazy try again' 12 | elif answerNumber == 5: 13 | return 'Ask again later' 14 | elif answerNumber == 6: 15 | return 'Concentrate and ask again' 16 | elif answerNumber == 7: 17 | return 'My reply is no' 18 | elif answerNumber == 8: 19 | return 'Outlook not so good' 20 | elif answerNumber == 9: 21 | return 'Very doubtful' 22 | 23 | r = random.randint(1, 9) 24 | fortune = getAnswer(r) 25 | print(fortune) 26 | -------------------------------------------------------------------------------- /automate_online-materials/ticTacToe.py: -------------------------------------------------------------------------------- 1 | theBoard = {'top-L': ' ', 'top-M': ' ', 'top-R': ' ', 2 | 'mid-L': ' ', 'mid-M': ' ', 'mid-R': ' ', 3 | 'low-L': ' ', 'low-M': ' ', 'low-R': ' '} 4 | def printBoard(board): 5 | print(board['top-L'] + '|' + board['top-M'] + '|' + board['top-R']) 6 | print('-+-+-') 7 | print(board['mid-L'] + '|' + board['mid-M'] + '|' + board['mid-R']) 8 | print('-+-+-') 9 | print(board['low-L'] + '|' + board['low-M'] + '|' + board['low-R']) 10 | 11 | turn = 'X' 12 | for i in range(9): 13 | printBoard(theBoard) 14 | print('Turn for ' + turn + '. Move on which space?') 15 | move = input() 16 | theBoard[move] = turn 17 | if turn == 'X': 18 | turn = 'O' 19 | else: 20 | turn = 'X' 21 | printBoard(theBoard) 22 | -------------------------------------------------------------------------------- /automate_online-materials/mcb.pyw: -------------------------------------------------------------------------------- 1 | #! python3 2 | # mcb.pyw - Saves and loads pieces of text to the clipboard. 3 | # Usage: py.exe mcb.pyw save - Saves clipboard to keyword. 4 | # py.exe mcb.pyw - Loads keyword to clipboard. 5 | # py.exe mcb.pyw list - Loads all keywords to clipboard. 6 | 7 | import shelve, pyperclip, sys 8 | 9 | mcbShelf = shelve.open('mcb') 10 | 11 | # Save clipboard content. 12 | if len(sys.argv) == 3 and sys.argv[1].lower() == 'save': 13 | mcbShelf[sys.argv[2]] = pyperclip.paste() 14 | elif len(sys.argv) == 2: 15 | # List keywords and load content. 16 | if sys.argv[1].lower() == 'list': 17 | pyperclip.copy(str(list(mcbShelf.keys()))) 18 | elif sys.argv[1] in mcbShelf: 19 | pyperclip.copy(mcbShelf[sys.argv[1]]) 20 | 21 | mcbShelf.close() 22 | -------------------------------------------------------------------------------- /14-csv-json/excelToCsv.py: -------------------------------------------------------------------------------- 1 | import csv 2 | import os 3 | import openpyxl 4 | 5 | for excelFile in os.listdir('.'): 6 | # Skip non-xlsx files, load the workbook object 7 | for sheetName in wb.get_sheet_names(): 8 | # Loop through every sheet in the workbook 9 | sheet = wb.get_sheet_by_name(sheetname) 10 | 11 | # Create the CSV filename from the Excel filename and sheet title 12 | # Create the csv.writer object for CSV file. 13 | 14 | # Loop through every row in the sheet. 15 | for rowNum in range(1, sheet.max_row+1): 16 | rowData = [] 17 | for colNum in range(1, sheet.max_column+1): 18 | # Append each cell's data to rowData 19 | 20 | # Write the rowData list to the CSV file. 21 | 22 | csvFile.close() 23 | -------------------------------------------------------------------------------- /06-str/printTable.py: -------------------------------------------------------------------------------- 1 | def getColWidth(table, widths): 2 | for i in range(len(table)): 3 | colWidth = 0 4 | for item in table[i]: 5 | widths[i] = max(widths[i], len(item)) 6 | 7 | 8 | def printTable(table, widths): 9 | rowNum = len(table) 10 | colNum = len(table[0]) 11 | for y in range(colNum): 12 | print(table[0][y].ljust(widths[0]), end=' ') 13 | for x in range(1, rowNum): 14 | print(table[x][y].ljust(widths[x]), end=' ') 15 | print() 16 | 17 | 18 | tableData = [['apples', 'oranges', 'cherries', 'banana'], 19 | ['Alice', 'Bob', 'Carol', 'David'], 20 | ['dogs', 'cats', 'moose', 'goose']] 21 | colWidths = [0] * len(tableData) 22 | 23 | 24 | getColWidth(tableData, colWidths) 25 | printTable(tableData, colWidths) 26 | -------------------------------------------------------------------------------- /11-web/README.md: -------------------------------------------------------------------------------- 1 | # web moduels 2 | * webbrowser: 是Python自带的,打开浏览器获取指定页面。 3 | * requests: 从因特网上下载文件和网页 4 | * Beautiful Soup: 解析HTML,即网页编写的格式 5 | * selenium: 启动并控制一个Web浏览器。selenium能够填写表单,并模拟鼠标在这个浏览器中点击。 6 | 7 | # webbrowser 8 |
 9 | import webbrowser
10 | webbrowser.open(https://cn.bing.com/ditu/Default.aspx?q=' + address)
11 | 
12 | 13 | # requests 14 | `pip install requests` 15 |
16 | import requests
17 | 
18 | res = requests.get('http://www.gutenberg.org/cache/epub/1112/pg1112.txt')
19 | try:
20 |     res.raise_for_status()
21 |     print(res.text[:250])
22 | except Exception as exc:
23 | 	print('There was a problem: %s' % (exc))
24 | 
25 | 26 | # BeautifulSoup 27 | `pip install beautifulsoup4` 28 |
29 | import bs4
30 | 
31 | 32 | # selenium 33 | install geckodriver 34 | https://github.com/mozilla/geckodriver 35 | -------------------------------------------------------------------------------- /12-excel/transposition.py: -------------------------------------------------------------------------------- 1 | import openpyxl 2 | import sys 3 | from openpyxl.utils.cell import get_column_letter 4 | 5 | if len(sys.argv) < 2: 6 | print('usage: py transposition.py [xlsx]') 7 | exit() 8 | 9 | xlsxFile = sys.argv[1] 10 | 11 | # Open xlsx and read it 12 | wbRead = openpyxl.load_workbook(xlsxFile) 13 | sheetRead = wbRead.get_active_sheet() 14 | 15 | # Create sheet to be write 16 | wbWrite = openpyxl.Workbook() 17 | sheetWrite = wbWrite.get_active_sheet() 18 | 19 | # Transposition 20 | for i in range(1, sheetRead.max_row+1): 21 | for j in range(1, sheetRead.max_column+1): 22 | coordRead = get_column_letter(j)+str(i) 23 | coordWrite = get_column_letter(i)+str(j) 24 | sheetWrite[coordWrite] = sheetRead[coordRead].value 25 | 26 | # save sheet to file 27 | wbWrite.save(xlsxFile+'.trans.xlsx') 28 | 29 | 30 | -------------------------------------------------------------------------------- /09-organize-file/sequence.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | import re 4 | 5 | def sequence(dir, prefix): 6 | # dir exists 7 | if not os.path.exists(dir): 8 | print('Directory not exists.') 9 | return 10 | 11 | # list all file and get the number of files with prefix 12 | filenum = 0 13 | filelist = [] 14 | for file in os.listdir(dir): 15 | if file.startswith(prefix): 16 | filenum += 1 17 | filelist.append(file) 18 | filelist.sort() 19 | 20 | # rename file 21 | print(filelist) 22 | for i in range(filenum): 23 | srcfile = os.path.join(dir, filelist[i]) 24 | dstfile = os.path.join(dir, prefix + '%03d'%(i+1) + '.txt') 25 | if srcfile != dstfile: 26 | print(srcfile, dstfile) 27 | shutil.move(srcfile, dstfile) 28 | 29 | sequence('demo', 'spam') -------------------------------------------------------------------------------- /17-image/drawAndText.py: -------------------------------------------------------------------------------- 1 | from PIL import Image, ImageDraw 2 | im = Image.new('RGBA', (200, 200), 'white') 3 | draw = ImageDraw.Draw(im) 4 | draw.line([(0, 0), (199, 0), (199, 199), (0, 199), (0, 0)], fill='black') 5 | draw.rectangle((20, 30, 60, 60), fill='blue') 6 | draw.ellipse((120, 30, 160, 60), fill='red') 7 | draw.polygon(((57, 87), (79, 62), (94, 85), (120, 90), (103, 113)), 8 | fill='brown') 9 | for i in range(100, 200, 10): 10 | draw.line([(i, 0), (200, i - 100)], fill='green') 11 | 12 | im.save('drawing.png') 13 | from PIL import ImageFont 14 | import os 15 | im = Image.new('RGBA', (200, 200), 'white') 16 | draw = ImageDraw.Draw(im) 17 | draw.text((20, 150), 'Hello', fill='purple') 18 | fontsFolder = 'C:/Windows/Fonts' 19 | arialFont = ImageFont.truetype(os.path.join(fontsFolder, 'arial.ttf'), 32) 20 | draw.text((100, 150), 'Howdy', fill='gray', font=arialFont) 21 | im.save('text.png') -------------------------------------------------------------------------------- /07-regex/isPhoneNumber.py: -------------------------------------------------------------------------------- 1 | def isPhoneNumber(text): 2 | if len(text) != 12: 3 | return False # not phone number-sized 4 | for i in range(0, 3): 5 | if not text[i].isdecimal(): 6 | return False # not an area code 7 | if text[3] != '-': 8 | return False # does not have first hyphen 9 | for i in range(4, 7): 10 | if not text[i].isdecimal(): 11 | return False # does not have first 3 digits 12 | if text[7] != '-': 13 | return False # does not have second hyphen 14 | for i in range(8, 12): 15 | if not text[i].isdecimal(): 16 | return False # does not have last 4 digits 17 | return True # "text" is a phone number! 18 | 19 | print('415-555-4242 is a phone number:') 20 | print(isPhoneNumber('415-555-4242')) 21 | print('Moshi moshi is a phone number:') 22 | print(isPhoneNumber('Moshi moshi')) 23 | -------------------------------------------------------------------------------- /08-file/mcb.pyw: -------------------------------------------------------------------------------- 1 | #! python3 2 | # mcb.pyw - Saves and loads pieces of text to the clipboard. 3 | # Usage: py.exe mcb.pyw save - Saves clipboard to keyword. 4 | # py.exe mcb.pyw - Loads keyword to clipboard. 5 | # py.exe mcb.pyw list - Loads all keywords to clipboard. 6 | 7 | import shelve, pyperclip, sys 8 | 9 | mcbShelf = shelve.open('mcb') 10 | 11 | # Save clipboard content. 12 | if len(sys.argv) == 3: 13 | if sys.argv[1].lower() == 'save': 14 | mcbShelf[sys.argv[2]] = pyperclip.paste() 15 | elif sys.argv[1].lower() == 'delete': 16 | del mcbShelf[sys.argv[2]] 17 | elif len(sys.argv) == 2: 18 | # List keywords and load content. 19 | if sys.argv[1].lower() == 'list': 20 | pyperclip.copy(str(list(mcbShelf.keys()))) 21 | elif sys.argv[1] in mcbShelf: 22 | pyperclip.copy(mcbShelf[sys.argv[1]]) 23 | 24 | mcbShelf.close() 25 | -------------------------------------------------------------------------------- /automate_online-materials/isPhoneNumber.py: -------------------------------------------------------------------------------- 1 | def isPhoneNumber(text): 2 | if len(text) != 12: 3 | return False # not phone number-sized 4 | for i in range(0, 3): 5 | if not text[i].isdecimal(): 6 | return False # not an area code 7 | if text[3] != '-': 8 | return False # does not have first hyphen 9 | for i in range(4, 7): 10 | if not text[i].isdecimal(): 11 | return False # does not have first 3 digits 12 | if text[7] != '-': 13 | return False # does not have second hyphen 14 | for i in range(8, 12): 15 | if not text[i].isdecimal(): 16 | return False # does not have last 4 digits 17 | return True # "text" is a phone number! 18 | 19 | print('415-555-4242 is a phone number:') 20 | print(isPhoneNumber('415-555-4242')) 21 | print('Moshi moshi is a phone number:') 22 | print(isPhoneNumber('Moshi moshi')) 23 | -------------------------------------------------------------------------------- /15-time/stopwatch.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # stopwatch.py - A simple stopwatch program. 3 | 4 | import time 5 | 6 | # Display the program's instructions. 7 | print('Press enter to begin. Afterwards, press ENTER to "click" the stopwatch. Press Ctrl-C to quit.') 8 | input() # press Enter to begin 9 | print('Started.') 10 | startTime = time.time() # get the first lap's start time 11 | lastTime = startTime 12 | lapNum = 1 13 | 14 | # Start tracking the lap times. 15 | try: 16 | while True: 17 | input() 18 | lapTime = round(time.time() - lastTime, 2) 19 | totalTime = round(time.time() - startTime, 2) 20 | print('Lap #%s: %s (%s)' % (lapNum, totalTime, lapTime), end='') 21 | lapNum += 1 22 | lastTime = time.time() # reset the last lap time 23 | except KeyboardInterrupt: 24 | # Handle the Ctrl-C exception to keep its error message from displaying. 25 | print('\nDone.') 26 | -------------------------------------------------------------------------------- /automate_online-materials/stopwatch.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # stopwatch.py - A simple stopwatch program. 3 | 4 | import time 5 | 6 | # Display the program's instructions. 7 | print('Press enter to begin. Afterwards, press ENTER to "click" the stopwatch. Press Ctrl-C to quit.') 8 | input() # press Enter to begin 9 | print('Started.') 10 | startTime = time.time() # get the first lap's start time 11 | lastTime = startTime 12 | lapNum = 1 13 | 14 | # Start tracking the lap times. 15 | try: 16 | while True: 17 | input() 18 | lapTime = round(time.time() - lastTime, 2) 19 | totalTime = round(time.time() - startTime, 2) 20 | print('Lap #%s: %s (%s)' % (lapNum, totalTime, lapTime), end='') 21 | lapNum += 1 22 | lastTime = time.time() # reset the last lap time 23 | except KeyboardInterrupt: 24 | # Handle the Ctrl-C exception to keep its error message from displaying. 25 | print('\nDone.') 26 | -------------------------------------------------------------------------------- /13-pdf-word/combinePdfs.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # combinePdfs.py - Combines all the PDFs in the current working directory into 3 | # a single PDF. 4 | 5 | import os 6 | import PyPDF2 7 | 8 | # Get all the PDF filenames. 9 | pdfFiles = [] 10 | for filename in os.listdir('.'): 11 | if filename.endswith('.pdf'): 12 | pdfFiles.append(filename) 13 | pdfFiles.sort() 14 | 15 | pdfWriter = PyPDF2.PdfFileWriter() 16 | 17 | # Loop through all the PDF files. 18 | for filename in pdfFiles: 19 | pdfFileObj = open(filename, 'rb') 20 | pdfReader = PyPDF2.PdfFileReader(pdfFileObj) 21 | 22 | # Loop through all the pages (except the first) and add them. 23 | for pageNum in range(1, pdfReader.numPages): 24 | pageObj = pdfReader.getPage(pageNum) 25 | pdfWriter.addPage(pageObj) 26 | 27 | # Save the resulting PDF to a file. 28 | pdfOutput = open('allminutes.pdf', 'wb') 29 | pdfWriter.write(pdfOutput) 30 | pdfOutput.close() 31 | -------------------------------------------------------------------------------- /automate_online-materials/combinePdfs.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # combinePdfs.py - Combines all the PDFs in the current working directory into 3 | # a single PDF. 4 | 5 | import PyPDF2, os 6 | 7 | # Get all the PDF filenames. 8 | pdfFiles = [] 9 | for filename in os.listdir('.'): 10 | if filename.endswith('.pdf'): 11 | pdfFiles.append(filename) 12 | pdfFiles.sort() 13 | 14 | pdfWriter = PyPDF2.PdfFileWriter() 15 | 16 | # Loop through all the PDF files. 17 | for filename in pdfFiles: 18 | pdfFileObj = open(filename, 'rb') 19 | pdfReader = PyPDF2.PdfFileReader(pdfFileObj) 20 | 21 | # Loop through all the pages (except the first) and add them. 22 | for pageNum in range(1, pdfReader.numPages): 23 | pageObj = pdfReader.getPage(pageNum) 24 | pdfWriter.addPage(pageObj) 25 | 26 | # Save the resulting PDF to a file. 27 | pdfOutput = open('allminutes.pdf', 'wb') 28 | pdfWriter.write(pdfOutput) 29 | pdfOutput.close() 30 | -------------------------------------------------------------------------------- /14-csv-json/removeCsvHeader.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # removeCsvHeader.py - Removes the header from all CSV files in the current 3 | # working directory. 4 | 5 | import csv 6 | import os 7 | 8 | os.makedirs('headerRemoved', exist_ok=True) 9 | 10 | # Loop through every file in the current working directory. 11 | for csvFilename in os.listdir('.'): 12 | if not csvFilename.endswith('.csv'): 13 | continue # skip non-csv files 14 | 15 | print('Removing header from ' + csvFilename + '...') 16 | 17 | # Read the CSV file in (skipping first row). 18 | csvRows = [] 19 | csvFileObj = open(csvFilename) 20 | readerObj = csv.reader(csvFileObj) 21 | for row in readerObj: 22 | if readerObj.line_num == 1: 23 | continue # skip first row 24 | csvRows.append(row) 25 | csvFileObj.close() 26 | 27 | # Write out the CSV file. 28 | csvFileObj = open(os.path.join('headerRemoved', csvFilename), 'w', newline='') 29 | csvWriter = csv.writer(csvFileObj) 30 | for row in csvRows: 31 | csvWriter.writerow(row) 32 | csvFileObj.close() 33 | -------------------------------------------------------------------------------- /automate_online-materials/removeCsvHeader.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # removeCsvHeader.py - Removes the header from all CSV files in the current 3 | # working directory. 4 | 5 | import csv, os 6 | 7 | os.makedirs('headerRemoved', exist_ok=True) 8 | 9 | # Loop through every file in the current working directory. 10 | for csvFilename in os.listdir('.'): 11 | if not csvFilename.endswith('.csv'): 12 | continue # skip non-csv files 13 | 14 | print('Removing header from ' + csvFilename + '...') 15 | 16 | # Read the CSV file in (skipping first row). 17 | csvRows = [] 18 | csvFileObj = open(csvFilename) 19 | readerObj = csv.reader(csvFileObj) 20 | for row in readerObj: 21 | if readerObj.line_num == 1: 22 | continue # skip first row 23 | csvRows.append(row) 24 | csvFileObj.close() 25 | 26 | # Write out the CSV file. 27 | csvFileObj = open(os.path.join('headerRemoved', csvFilename), 'w', newline='') 28 | csvWriter = csv.writer(csvFileObj) 29 | for row in csvRows: 30 | csvWriter.writerow(row) 31 | csvFileObj.close() 32 | -------------------------------------------------------------------------------- /automate_online-materials/quickWeather.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # quickWeather.py - Prints the current weather for a location from the command line. 3 | 4 | import json, requests, sys 5 | 6 | # Compute location from command line arguments. 7 | if len(sys.argv) < 2: 8 | print('Usage: quickWeather.py location') 9 | sys.exit() 10 | location = ' '.join(sys.argv[1:]) 11 | 12 | # Download the JSON data from OpenWeatherMap.org's API 13 | url ='http://api.openweathermap.org/data/2.5/forecast/daily?q=%s&cnt=3' % (location) 14 | response = requests.get(url) 15 | response.raise_for_status() 16 | 17 | # Load JSON data into a Python variable. 18 | weatherData = json.loads(response.text) 19 | 20 | # Print weather descriptions. 21 | w = weatherData['list'] 22 | print('Current weather in %s:' % (location)) 23 | print(w[0]['weather'][0]['main'], '-', w[0]['weather'][0]['description']) 24 | print() 25 | print('Tomorrow:') 26 | print(w[1]['weather'][0]['main'], '-', w[1]['weather'][0]['description']) 27 | print() 28 | print('Day after tomorrow:') 29 | print(w[2]['weather'][0]['main'], '-', w[2]['weather'][0]['description']) 30 | -------------------------------------------------------------------------------- /14-csv-json/quickWeather.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # quickWeather.py - Prints the current weather for a location from the command line. 3 | 4 | import json 5 | import sys 6 | import requests 7 | 8 | # Compute location from command line arguments. 9 | if len(sys.argv) < 2: 10 | print('Usage: quickWeather.py location') 11 | sys.exit() 12 | location = ' '.join(sys.argv[1:]) 13 | 14 | # Download the JSON data from OpenWeatherMap.org's API 15 | url ='http://api.openweathermap.org/data/2.5/forecast/daily?q=%s&cnt=3' % (location) 16 | response = requests.get(url) 17 | response.raise_for_status() 18 | 19 | # Load JSON data into a Python variable. 20 | weatherData = json.loads(response.text) 21 | 22 | # Print weather descriptions. 23 | w = weatherData['list'] 24 | print('Current weather in %s:' % (location)) 25 | print(w[0]['weather'][0]['main'], '-', w[0]['weather'][0]['description']) 26 | print() 27 | print('Tomorrow:') 28 | print(w[1]['weather'][0]['main'], '-', w[1]['weather'][0]['description']) 29 | print() 30 | print('Day after tomorrow:') 31 | print(w[2]['weather'][0]['main'], '-', w[2]['weather'][0]['description']) 32 | -------------------------------------------------------------------------------- /12-excel/blankRowInserter.py: -------------------------------------------------------------------------------- 1 | import openpyxl 2 | import sys 3 | from openpyxl.utils.cell import get_column_letter 4 | 5 | if len(sys.argv) < 4: 6 | print('usage: py blankRowInserter.py [afterTheRow] [blankRowsNumber] [xlsx]') 7 | exit() 8 | 9 | afterTheRow = int(sys.argv[1]) 10 | blankRowsNumber = int(sys.argv[2]) 11 | xlsxFile = sys.argv[3] 12 | 13 | # Open xlsx and read it 14 | wbRead = openpyxl.load_workbook(xlsxFile) 15 | sheetRead = wbRead.get_active_sheet() 16 | 17 | # Create sheet to be write 18 | wbWrite = openpyxl.Workbook() 19 | sheetWrite = wbWrite.get_active_sheet() 20 | 21 | # copy first afterTheRow rows 22 | for i in range(1, afterTheRow+1): 23 | for j in range(1, sheetRead.max_column+1): 24 | coord = get_column_letter(j)+str(i) 25 | sheetWrite[coord] = sheetRead[coord].value 26 | # copy latter rows 27 | 28 | for i in range(afterTheRow+1, sheetRead.max_row+1): 29 | for j in range(1, sheetRead.max_column+1): 30 | coordWrite = get_column_letter(j)+str(i+blankRowsNumber) 31 | coordRead = get_column_letter(j)+str(i) 32 | sheetWrite[coordWrite] = sheetRead[coordRead].value 33 | 34 | # save sheet to file 35 | wbWrite.save(xlsxFile+'.blank.xlsx') 36 | 37 | 38 | -------------------------------------------------------------------------------- /13-pdf-word/batchEncryptPdf.py: -------------------------------------------------------------------------------- 1 | import PyPDF2 2 | import os 3 | 4 | path = '' 5 | password = '' 6 | 7 | # get all pdf file in pointed directory 8 | for dirpath, dirnames, filenames in os.walk(path): 9 | # open each pdf file and get first page of it 10 | for filename in filenames: 11 | if not filename.endswith('.pdf'): 12 | continue 13 | filepath = os.path.join(dirpath, filename) 14 | pdfFile = PyPDF2.open(filepath, 'rb') 15 | pdfReader = PyPDF2.PdfFileReader(pdfFile) 16 | # if catch Exception then decrypt the file with given pass 17 | try: 18 | pdfReader.getPage(0) 19 | except err: 20 | if pdfReader.decrypt(password): 21 | pdfWriter = PyPDF2.PdfFileWriter() 22 | for page in pdfReader.numPages: 23 | pdfWriter.addPage(pdfReader.getPage(0)) 24 | decryptPdfFile = open(destDirectory+filename+'_encrypted.pdf', 'wb') 25 | pdfWriter(decryptPdfFile) 26 | decryptPdfFile.close() 27 | else: 28 | # if pass is error, the print message and continue 29 | print(msg) 30 | continue 31 | pdfFile.close() 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /automate_online-materials/downloadXkcd.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # downloadXkcd.py - Downloads every single XKCD comic. 3 | 4 | import requests, os, bs4 5 | 6 | url = 'http://xkcd.com' # starting url 7 | os.makedirs('xkcd', exist_ok=True) # store comics in ./xkcd 8 | while not url.endswith('#'): 9 | # Download the page. 10 | print('Downloading page %s...' % url) 11 | res = requests.get(url) 12 | res.raise_for_status() 13 | 14 | soup = bs4.BeautifulSoup(res.text) 15 | 16 | # Find the URL of the comic image. 17 | comicElem = soup.select('#comic img') 18 | if comicElem == []: 19 | print('Could not find comic image.') 20 | else: 21 | comicUrl = comicElem[0].get('src') 22 | # Download the image. 23 | print('Downloading image %s...' % (comicUrl)) 24 | res = requests.get(comicUrl) 25 | res.raise_for_status() 26 | 27 | # Save the image to ./xkcd 28 | imageFile = open(os.path.join('xkcd', os.path.basename(comicUrl)), 'wb') 29 | for chunk in res.iter_content(100000): 30 | imageFile.write(chunk) 31 | imageFile.close() 32 | 33 | # Get the Prev button's url. 34 | prevLink = soup.select('a[rel="prev"]')[0] 35 | url = 'http://xkcd.com' + prevLink.get('href') 36 | 37 | print('Done.') 38 | -------------------------------------------------------------------------------- /11-web/downloadXkcd.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # downloadXkcd.py - Downloads every single XKCD comic. 3 | 4 | import requests, os, bs4 5 | 6 | url = 'https://xkcd.com' # starting url 7 | os.makedirs('xkcd', exist_ok=True) # store comics in ./xkcd 8 | while not url.endswith('#'): 9 | # Download the page. 10 | print('Downloading page %s...' % url) 11 | res = requests.get(url) 12 | res.raise_for_status() 13 | 14 | soup = bs4.BeautifulSoup(res.text, 'html.parser') 15 | 16 | # Find the URL of the comic image. 17 | comicElem = soup.select('#comic img') 18 | if comicElem == []: 19 | print('Could not find comic image.') 20 | else: 21 | comicUrl = comicElem[0].get('src') 22 | # Download the image. 23 | print('Downloading image %s...' % (comicUrl)) 24 | res = requests.get(str('http:' + comicUrl)) 25 | res.raise_for_status() 26 | 27 | # Save the image to ./xkcd 28 | imageFile = open(os.path.join('xkcd', os.path.basename(comicUrl)), 'wb') 29 | for chunk in res.iter_content(100000): 30 | imageFile.write(chunk) 31 | imageFile.close() 32 | 33 | # Get the Prev button's url. 34 | prevLink = soup.select('a[rel="prev"]')[0] 35 | url = 'http://xkcd.com' + prevLink.get('href') 36 | 37 | print('Done.') 38 | -------------------------------------------------------------------------------- /automate_online-materials/phoneAndEmail.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # phoneAndEmail.py - Finds phone numbers and email addresses on the clipboard. 3 | 4 | import pyperclip, re 5 | 6 | phoneRegex = re.compile(r'''( 7 | (\d{3}|\(\d{3}\))? # area code 8 | (\s|-|\.)? # separator 9 | (\d{3}) # first 3 digits 10 | (\s|-|\.) # separator 11 | (\d{4}) # last 4 digits 12 | (\s*(ext|x|ext.)\s*(\d{2,5}))? # extension 13 | )''', re.VERBOSE) 14 | 15 | # Create email regex. 16 | emailRegex = re.compile(r'''( 17 | [a-zA-Z0-9._%+-]+ # username 18 | @ # @ symbol 19 | [a-zA-Z0-9.-]+ # domain name 20 | (\.[a-zA-Z]{2,4}){1,2} # dot-something 21 | )''', re.VERBOSE) 22 | 23 | # Find matches in clipboard text. 24 | text = str(pyperclip.paste()) 25 | 26 | matches = [] 27 | for groups in phoneRegex.findall(text): 28 | phoneNum = '-'.join([groups[1], groups[3], groups[5]]) 29 | if groups[8] != '': 30 | phoneNum += ' x' + groups[8] 31 | matches.append(phoneNum) 32 | for groups in emailRegex.findall(text): 33 | matches.append(groups[0]) 34 | 35 | # Copy results to the clipboard. 36 | if len(matches) > 0: 37 | pyperclip.copy('\n'.join(matches)) 38 | print('Copied to clipboard:') 39 | print('\n'.join(matches)) 40 | else: 41 | print('No phone numbers or email addresses found.') 42 | -------------------------------------------------------------------------------- /12-excel/readCensusExcel.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # readCensusExcel.py - Tabulates population and number of census tracts for 3 | # each county. 4 | 5 | import openpyxl, pprint 6 | print('Opening workbook...') 7 | wb = openpyxl.load_workbook('censuspopdata.xlsx') 8 | sheet = wb.get_sheet_by_name('Population by Census Tract') 9 | countyData = {} 10 | # Fill in countyData with each county's population and tracts. 11 | print('Reading rows...') 12 | for row in range(2, sheet.max_row + 1): 13 | # Each row in the spreadsheet has data for one census tract. 14 | state = sheet['B' + str(row)].value 15 | county = sheet['C' + str(row)].value 16 | pop = sheet['D' + str(row)].value 17 | 18 | # Make sure the key for this state exists. 19 | countyData.setdefault(state, {}) 20 | # Make sure the key for this county in this state exists. 21 | countyData[state].setdefault(county, {'tracts': 0, 'pop': 0}) 22 | 23 | # Each row represents one census tract, so increment by one. 24 | countyData[state][county]['tracts'] += 1 25 | # Increase the county pop by the pop in this census tract. 26 | countyData[state][county]['pop'] += int(pop) 27 | 28 | # Open a new text file and write the contents of countyData to it. 29 | print('Writing results...') 30 | resultFile = open('census2010.py', 'w') 31 | resultFile.write('allData = ' + pprint.pformat(countyData)) 32 | resultFile.close() 33 | print('Done.') 34 | -------------------------------------------------------------------------------- /07-regex/phoneAndEmail.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # phoneAndEmail.py - Finds phone numbers and email addresses on the clipboard. 3 | 4 | import pyperclip, re 5 | 6 | phoneRegex = re.compile(r'''( 7 | (\d{3}|\(\d{3}\))? # area code 8 | (\s|-|\.)? # separator 9 | (\d{3}) # first 3 digits 10 | (\s|-|\.) # separator 11 | (\d{4}) # last 4 digits 12 | (\s*(ext|x|ext.)\s*(\d{2,5}))? # extension 13 | )''', re.VERBOSE) 14 | 15 | # Create email regex. 16 | emailRegex = re.compile(r'''( 17 | [a-zA-Z0-9._%+-]+ # username 18 | @ # @ symbol 19 | [a-zA-Z0-9.-]+ # domain name 20 | (\.[a-zA-Z]{2,4}){1,2} # dot-something 21 | )''', re.VERBOSE) 22 | 23 | # Find matches in clipboard text. 24 | text = str(pyperclip.paste()) 25 | 26 | matches = [] 27 | for groups in phoneRegex.findall(text): 28 | phoneNum = '-'.join([groups[1], groups[3], groups[5]]) 29 | if groups[8] != '': 30 | phoneNum += ' x' + groups[8] 31 | matches.append(phoneNum) 32 | for groups in emailRegex.findall(text): 33 | matches.append(groups[0]) 34 | 35 | # Copy results to the clipboard. 36 | if len(matches) > 0: 37 | pyperclip.copy('\n'.join(matches)) 38 | print('Copied to clipboard:') 39 | print('\n'.join(matches)) 40 | else: 41 | print('No phone numbers or email addresses found.') 42 | -------------------------------------------------------------------------------- /automate_online-materials/readCensusExcel.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # readCensusExcel.py - Tabulates population and number of census tracts for 3 | # each county. 4 | 5 | import openpyxl, pprint 6 | print('Opening workbook...') 7 | wb = openpyxl.load_workbook('censuspopdata.xlsx') 8 | sheet = wb.get_sheet_by_name('Population by Census Tract') 9 | countyData = {} 10 | # Fill in countyData with each county's population and tracts. 11 | print('Reading rows...') 12 | for row in range(2, sheet.get_highest_row() + 1): 13 | # Each row in the spreadsheet has data for one census tract. 14 | state = sheet['B' + str(row)].value 15 | county = sheet['C' + str(row)].value 16 | pop = sheet['D' + str(row)].value 17 | 18 | # Make sure the key for this state exists. 19 | countyData.setdefault(state, {}) 20 | # Make sure the key for this county in this state exists. 21 | countyData[state].setdefault(county, {'tracts': 0, 'pop': 0}) 22 | 23 | # Each row represents one census tract, so increment by one. 24 | countyData[state][county]['tracts'] += 1 25 | # Increase the county pop by the pop in this census tract. 26 | countyData[state][county]['pop'] += int(pop) 27 | 28 | # Open a new text file and write the contents of countyData to it. 29 | print('Writing results...') 30 | resultFile = open('census2010.py', 'w') 31 | resultFile.write('allData = ' + pprint.pformat(countyData)) 32 | resultFile.close() 33 | print('Done.') 34 | -------------------------------------------------------------------------------- /16-email-sms/sendDuesReminders.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # sendDuesReminders.py - Sends emails based on their status in spreadsheet. 3 | 4 | import openpyxl, smtplib, sys 5 | 6 | # Open the spreadsheet and get the latest dues status. 7 | wb = openpyxl.load_workbook('duesRecords.xlsx') 8 | sheet = wb.get_sheet_by_name('Sheet1') 9 | 10 | lastCol = sheet.get_highest_column() 11 | latestMonth = sheet.cell(row=1, column=lastCol).value 12 | 13 | unpaidMembers = {} 14 | # Check each member's payment status 15 | for r in range(2, sheet.get_highest_row() + 1): 16 | payment = sheet.cell(row=r, column=lastCol).value 17 | if payment != 'paid': 18 | name = sheet.cell(row=r, column=1).value 19 | email = sheet.cell(row=r, column=2).value 20 | unpaidMembers[name] = email 21 | 22 | # Log in to email account. 23 | smtpObj = smtplib.SMTP('smtp.gmail.com', 587) 24 | smtpObj.ehlo() 25 | smtpObj.starttls() 26 | smtpObj.login('my_email_address@gmail.com', sys.argv[1]) 27 | 28 | # Send out reminder emails. 29 | for name, email in unpaidMembers.items(): 30 | body = 'Subject: %s dues unpaid.\nDear %s,\nRecords show that you have not paid dues for %s. Please make this payment as soon as possible. Thank you!' % (latestMonth, name, latestMonth) 31 | print('Sending email to %s...' % email) 32 | sendmailStatus = smtpObj.sendmail('my_email_address@gmail.com', email, body) 33 | 34 | if sendmailStatus != {}: 35 | print('There was a problem sending email to %s: %s' % (email, sendmailStatus)) 36 | smtpObj.quit() 37 | -------------------------------------------------------------------------------- /automate_online-materials/sendDuesReminders.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # sendDuesReminders.py - Sends emails based on their status in spreadsheet. 3 | 4 | import openpyxl, smtplib, sys 5 | 6 | # Open the spreadsheet and get the latest dues status. 7 | wb = openpyxl.load_workbook('duesRecords.xlsx') 8 | sheet = wb.get_sheet_by_name('Sheet1') 9 | 10 | lastCol = sheet.get_highest_column() 11 | latestMonth = sheet.cell(row=1, column=lastCol).value 12 | 13 | unpaidMembers = {} 14 | # Check each member's payment status 15 | for r in range(2, sheet.get_highest_row() + 1): 16 | payment = sheet.cell(row=r, column=lastCol).value 17 | if payment != 'paid': 18 | name = sheet.cell(row=r, column=1).value 19 | email = sheet.cell(row=r, column=2).value 20 | unpaidMembers[name] = email 21 | 22 | # Log in to email account. 23 | smtpObj = smtplib.SMTP('smtp.gmail.com', 587) 24 | smtpObj.ehlo() 25 | smtpObj.starttls() 26 | smtpObj.login('my_email_address@gmail.com', sys.argv[1]) 27 | 28 | # Send out reminder emails. 29 | for name, email in unpaidMembers.items(): 30 | body = 'Subject: %s dues unpaid.\nDear %s,\nRecords show that you have not paid dues for %s. Please make this payment as soon as possible. Thank you!' % (latestMonth, name, latestMonth) 31 | print('Sending email to %s...' % email) 32 | sendmailStatus = smtpObj.sendmail('my_email_address@gmail.com', email, body) 33 | 34 | if sendmailStatus != {}: 35 | print('There was a problem sending email to %s: %s' % (email, sendmailStatus)) 36 | smtpObj.quit() 37 | -------------------------------------------------------------------------------- /09-organize-file/backupToZip.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # backupToZip.py 3 | # Copies an entire folder and its contents into 4 | # a zip file whose filename increments. 5 | 6 | import zipfile, os 7 | 8 | def backupToZip(folder): 9 | # Backup the entire contents of "folder" into a zip file. 10 | 11 | folder = os.path.abspath(folder) # make sure folder is absolute 12 | 13 | # Figure out the filename this code should used based on 14 | # what files already exist. 15 | number = 1 16 | while True: 17 | zipFilename = os.path.basename(folder) + '_' + str(number) + '.zip' 18 | if not os.path.exists(zipFilename): 19 | break 20 | number = number + 1 21 | 22 | # Create the zip file. 23 | print('Creating %s...' % (zipFilename)) 24 | backupZip = zipfile.ZipFile(zipFilename, 'w') 25 | 26 | # Walk the entire folder tree and compress the files in each folder. 27 | for foldername, subfolders, filenames in os.walk(folder): 28 | print('Adding files in %s...' % (foldername)) 29 | # Add the current folder to the ZIP file. 30 | backupZip.write(foldername) 31 | 32 | # Add all the files in this folder to the ZIP file. 33 | for filename in filenames: 34 | if filename.startswith(os.path.basename(folder) + '_') and filename.endswith('.zip'): 35 | continue # don't backup the backup ZIP files 36 | backupZip.write(os.path.join(foldername, filename)) 37 | backupZip.close() 38 | print('Done.') 39 | 40 | 41 | backupToZip('C:\\delicious') 42 | -------------------------------------------------------------------------------- /09-organize-file/renameDates.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # renameDates.py - Renames filenames with American MM-DD-YYYY date format 3 | # to European DD-MM-YYYY. 4 | 5 | import shutil, os, re 6 | 7 | # Create a regex that matches files with the American date format. 8 | datePattern = re.compile(r"""^(.*?) # all text before the date 9 | ((0|1)?\d)- # one or two digits for the month 10 | ((0|1|2|3)?\d)- # one or two digits for the day 11 | ((19|20)\d\d) # four digits for the year (must start with 19 or 20) 12 | (.*?)$ # all text after the date 13 | """, re.VERBOSE) 14 | 15 | # Loop over the files in the working directory. 16 | for amerFilename in os.listdir('.'): 17 | mo = datePattern.search(amerFilename) 18 | 19 | # Skip files without a date. 20 | if mo == None: 21 | continue 22 | 23 | # Get the different parts of the filename. 24 | beforePart = mo.group(1) 25 | monthPart = mo.group(2) 26 | dayPart = mo.group(4) 27 | yearPart = mo.group(6) 28 | afterPart = mo.group(8) 29 | 30 | # Form the European-style filename. 31 | euroFilename = beforePart + dayPart + '-' + monthPart + '-' + yearPart + afterPart 32 | 33 | # Get the full, absolute file paths. 34 | absWorkingDir = os.path.abspath('.') 35 | amerFilename = os.path.join(absWorkingDir, amerFilename) 36 | euroFilename = os.path.join(absWorkingDir, euroFilename) 37 | 38 | # Rename the files. 39 | print('Renaming "%s" to "%s"...' % (amerFilename, euroFilename)) 40 | #shutil.move(amerFilename, euroFilename) # uncomment after testing 41 | -------------------------------------------------------------------------------- /automate_online-materials/backupToZip.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # backupToZip.py 3 | # Copies an entire folder and its contents into 4 | # a zip file whose filename increments. 5 | 6 | import zipfile, os 7 | 8 | def backupToZip(folder): 9 | # Backup the entire contents of "folder" into a zip file. 10 | 11 | folder = os.path.abspath(folder) # make sure folder is absolute 12 | 13 | # Figure out the filename this code should used based on 14 | # what files already exist. 15 | number = 1 16 | while True: 17 | zipFilename = os.path.basename(folder) + '_' + str(number) + '.zip' 18 | if not os.path.exists(zipFilename): 19 | break 20 | number = number + 1 21 | 22 | # Create the zip file. 23 | print('Creating %s...' % (zipFilename)) 24 | backupZip = zipfile.ZipFile(zipFilename, 'w') 25 | 26 | # Walk the entire folder tree and compress the files in each folder. 27 | for foldername, subfolders, filenames in os.walk(folder): 28 | print('Adding files in %s...' % (foldername)) 29 | # Add the current folder to the ZIP file. 30 | backupZip.write(foldername) 31 | 32 | # Add all the files in this folder to the ZIP file. 33 | for filename in filenames: 34 | if filename.startswith(os.path.basename(folder) + '_') and filename.endswith('.zip'): 35 | continue # don't backup the backup ZIP files 36 | backupZip.write(os.path.join(foldername, filename)) 37 | backupZip.close() 38 | print('Done.') 39 | 40 | 41 | backupToZip('C:\\delicious') 42 | -------------------------------------------------------------------------------- /automate_online-materials/renameDates.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # renameDates.py - Renames filenames with American MM-DD-YYYY date format 3 | # to European DD-MM-YYYY. 4 | 5 | import shutil, os, re 6 | 7 | # Create a regex that matches files with the American date format. 8 | datePattern = re.compile(r"""^(.*?) # all text before the date 9 | ((0|1)?\d)- # one or two digits for the month 10 | ((0|1|2|3)?\d)- # one or two digits for the day 11 | ((19|20)\d\d) # four digits for the year (must start with 19 or 20) 12 | (.*?)$ # all text after the date 13 | """, re.VERBOSE) 14 | 15 | # Loop over the files in the working directory. 16 | for amerFilename in os.listdir('.'): 17 | mo = datePattern.search(amerFilename) 18 | 19 | # Skip files without a date. 20 | if mo == None: 21 | continue 22 | 23 | # Get the different parts of the filename. 24 | beforePart = mo.group(1) 25 | monthPart = mo.group(2) 26 | dayPart = mo.group(4) 27 | yearPart = mo.group(6) 28 | afterPart = mo.group(8) 29 | 30 | # Form the European-style filename. 31 | euroFilename = beforePart + dayPart + '-' + monthPart + '-' + yearPart + afterPart 32 | 33 | # Get the full, absolute file paths. 34 | absWorkingDir = os.path.abspath('.') 35 | amerFilename = os.path.join(absWorkingDir, amerFilename) 36 | euroFilename = os.path.join(absWorkingDir, euroFilename) 37 | 38 | # Rename the files. 39 | print('Renaming "%s" to "%s"...' % (amerFilename, euroFilename)) 40 | #shutil.move(amerFilename, euroFilename) # uncomment after testing 41 | -------------------------------------------------------------------------------- /17-image/resizeAndAddLogo.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # resizeAndAddLogo.py - Resizes all images in current working directory to fit 3 | # in a 300x300 square, and adds catlogo.png to the lower-right corner. 4 | 5 | import os 6 | from PIL import Image 7 | 8 | SQUARE_FIT_SIZE = 300 9 | LOGO_FILENAME = 'catlogo.png' 10 | 11 | logoIm = Image.open(LOGO_FILENAME) 12 | logoWidth, logoHeight = logoIm.size 13 | 14 | os.makedirs('withLogo', exist_ok=True) 15 | # Loop over all files in the working directory. 16 | for filename in os.listdir('.'): 17 | if not (filename.endswith('.png') or filename.endswith('.jpg')) \ 18 | or filename == LOGO_FILENAME: 19 | continue # skip non-image files and the logo file itself 20 | 21 | im = Image.open(filename) 22 | width, height = im.size 23 | 24 | # Check if image needs to be resized. 25 | if width > SQUARE_FIT_SIZE and height > SQUARE_FIT_SIZE: 26 | # Calculate the new width and height to resize to. 27 | if width > height: 28 | height = int((SQUARE_FIT_SIZE / width) * height) 29 | width = SQUARE_FIT_SIZE 30 | else: 31 | width = int((SQUARE_FIT_SIZE / height) * width) 32 | height = SQUARE_FIT_SIZE 33 | 34 | # Resize the image. 35 | print('Resizing %s...' % (filename)) 36 | im = im.resize((width, height)) 37 | 38 | # Add logo. 39 | print('Adding logo to %s...' % (filename)) 40 | im.paste(logoIm, (width - logoWidth, height - logoHeight), logoIm) 41 | 42 | # Save changes. 43 | im.save(os.path.join('withLogo', filename)) 44 | -------------------------------------------------------------------------------- /automate_online-materials/resizeAndAddLogo.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # resizeAndAddLogo.py - Resizes all images in current working directory to fit 3 | # in a 300x300 square, and adds catlogo.png to the lower-right corner. 4 | 5 | import os 6 | from PIL import Image 7 | 8 | SQUARE_FIT_SIZE = 300 9 | LOGO_FILENAME = 'catlogo.png' 10 | 11 | logoIm = Image.open(LOGO_FILENAME) 12 | logoWidth, logoHeight = logoIm.size 13 | 14 | os.makedirs('withLogo', exist_ok=True) 15 | # Loop over all files in the working directory. 16 | for filename in os.listdir('.'): 17 | if not (filename.endswith('.png') or filename.endswith('.jpg')) \ 18 | or filename == LOGO_FILENAME: 19 | continue # skip non-image files and the logo file itself 20 | 21 | im = Image.open(filename) 22 | width, height = im.size 23 | 24 | # Check if image needs to be resized. 25 | if width > SQUARE_FIT_SIZE and height > SQUARE_FIT_SIZE: 26 | # Calculate the new width and height to resize to. 27 | if width > height: 28 | height = int((SQUARE_FIT_SIZE / width) * height) 29 | width = SQUARE_FIT_SIZE 30 | else: 31 | width = int((SQUARE_FIT_SIZE / height) * width) 32 | height = SQUARE_FIT_SIZE 33 | 34 | # Resize the image. 35 | print('Resizing %s...' % (filename)) 36 | im = im.resize((width, height)) 37 | 38 | # Add logo. 39 | print('Adding logo to %s...' % (filename)) 40 | im.paste(logoIm, (width - logoWidth, height - logoHeight), logoIm) 41 | 42 | # Save changes. 43 | im.save(os.path.join('withLogo', filename)) 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | local_settings.py 56 | 57 | # Flask stuff: 58 | instance/ 59 | .webassets-cache 60 | 61 | # Scrapy stuff: 62 | .scrapy 63 | 64 | # Sphinx documentation 65 | docs/_build/ 66 | 67 | # PyBuilder 68 | target/ 69 | 70 | # Jupyter Notebook 71 | .ipynb_checkpoints 72 | 73 | # pyenv 74 | .python-version 75 | 76 | # celery beat schedule file 77 | celerybeat-schedule 78 | 79 | # SageMath parsed files 80 | *.sage.py 81 | 82 | # dotenv 83 | .env 84 | 85 | # virtualenv 86 | .venv 87 | venv/ 88 | ENV/ 89 | 90 | # Spyder project settings 91 | .spyderproject 92 | .spyproject 93 | 94 | # Rope project settings 95 | .ropeproject 96 | 97 | # mkdocs documentation 98 | /site 99 | 100 | # mypy 101 | .mypy_cache/ 102 | 103 | # vs code 104 | .vscode -------------------------------------------------------------------------------- /15-time/multidownloadXkcd.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # multidownloadXkcd.py - Downloads XKCD comics using multiple threads. 3 | 4 | import requests, os, bs4, threading 5 | os.makedirs('xkcd', exist_ok=True) # store comics in ./xkcd 6 | 7 | def downloadXkcd(startComic, endComic): 8 | for urlNumber in range(startComic, endComic): 9 | # Download the page. 10 | print('Downloading page http://xkcd.com/%s...' % (urlNumber)) 11 | res = requests.get('http://xkcd.com/%s' % (urlNumber)) 12 | res.raise_for_status() 13 | 14 | soup = bs4.BeautifulSoup(res.text) 15 | 16 | # Find the URL of the comic image. 17 | comicElem = soup.select('#comic img') 18 | if comicElem == []: 19 | print('Could not find comic image.') 20 | else: 21 | comicUrl = comicElem[0].get('src') 22 | # Download the image. 23 | print('Downloading image %s...' % (comicUrl)) 24 | res = requests.get(comicUrl) 25 | res.raise_for_status() 26 | 27 | # Save the image to ./xkcd 28 | imageFile = open(os.path.join('xkcd', os.path.basename(comicUrl)), 'wb') 29 | for chunk in res.iter_content(100000): 30 | imageFile.write(chunk) 31 | imageFile.close() 32 | 33 | # Create and start the Thread objects. 34 | downloadThreads = [] # a list of all the Thread objects 35 | for i in range(0, 1400, 100): # loops 14 times, creates 14 threads 36 | downloadThread = threading.Thread(target=downloadXkcd, args=(i, i + 99)) 37 | downloadThreads.append(downloadThread) 38 | downloadThread.start() 39 | 40 | # Wait for all threads to end. 41 | for downloadThread in downloadThreads: 42 | downloadThread.join() 43 | print('Done.') 44 | -------------------------------------------------------------------------------- /17-image/imageOp.py: -------------------------------------------------------------------------------- 1 | catIm = Image.open('zophie.png') 2 | width, height = catIm.size 3 | catIm.save('zophie.jpg') 4 | im = Image.new('RGBA', (100,200), 'purple') 5 | im.save('purpleImage.png') 6 | im2 = Image.new('RGBA', (20, 20)) 7 | im2.save('transparentImage.png') 8 | croppedIm = catIm.crop((335,345, 565,560)) 9 | croppedIm.save('cropped.png') 10 | catCopyIm = catIm.copy() 11 | facedIm = catIm.crop((335,345, 565,560)) 12 | faceIm = catIm.crop((335,345, 565,560)) 13 | catCopyIm.paste(faceIm, (0, 0)) 14 | catCopyIm.paste(faceIm, (400, 500)) 15 | catCopyIm.save('pasted.png') 16 | w, h = catIm.size 17 | fw, fh = faceIm.size 18 | catCopyTwo = catIm.copy() 19 | for left in range(0, w, fw): 20 | for top in range(0, h, fh): 21 | print(left, top) 22 | catCopyTwo.paste(faceIm, (left, top)) 23 | 24 | catCopyTwo.save('tiled.png') 25 | qIm = catIm.resize((int(w/2), int(h/2))) 26 | 27 | qIm.save('quartersized.png') 28 | sveltedIm = catIm.resize((w, h+300)) 29 | 30 | sveltedIm.save('svelte.png') 31 | catIm.rotate(90).save('rotated90.png') 32 | catIm.rotate(180).save('rotated180.png') 33 | catIm.rotate(270).save('rotated270.png') 34 | catIm.rotate(6).save('rotated6.png') 35 | catIm.rotate(6, expand=True).save('rotated6_expanded.png') 36 | im = Image.new('RGBA', (100, 100)) 37 | im.getpixel((0,0)) 38 | (0, 0, 0, 0) 39 | for x in range(100): 40 | for y in range(50): 41 | im.putpixel((x, y), (210, 210, 210)) 42 | 43 | for x in range(100): 44 | for y in range(50, 100): 45 | im.putpixel((x, y), ImageColor.getcolor('darkgray', 'RGBA')) 46 | 47 | 48 | from PIL import ImageColor 49 | for x in range(100): 50 | for y in range(50, 100): 51 | im.putpixel((x, y), ImageColor.getcolor('darkgray', 'RGBA')) 52 | 53 | im.save('putPixel.png') -------------------------------------------------------------------------------- /automate_online-materials/multidownloadXkcd.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # multidownloadXkcd.py - Downloads XKCD comics using multiple threads. 3 | 4 | import requests, os, bs4, threading 5 | os.makedirs('xkcd', exist_ok=True) # store comics in ./xkcd 6 | 7 | def downloadXkcd(startComic, endComic): 8 | for urlNumber in range(startComic, endComic): 9 | # Download the page. 10 | print('Downloading page http://xkcd.com/%s...' % (urlNumber)) 11 | res = requests.get('http://xkcd.com/%s' % (urlNumber)) 12 | res.raise_for_status() 13 | 14 | soup = bs4.BeautifulSoup(res.text) 15 | 16 | # Find the URL of the comic image. 17 | comicElem = soup.select('#comic img') 18 | if comicElem == []: 19 | print('Could not find comic image.') 20 | else: 21 | comicUrl = comicElem[0].get('src') 22 | # Download the image. 23 | print('Downloading image %s...' % (comicUrl)) 24 | res = requests.get(comicUrl) 25 | res.raise_for_status() 26 | 27 | # Save the image to ./xkcd 28 | imageFile = open(os.path.join('xkcd', os.path.basename(comicUrl)), 'wb') 29 | for chunk in res.iter_content(100000): 30 | imageFile.write(chunk) 31 | imageFile.close() 32 | 33 | # Create and start the Thread objects. 34 | downloadThreads = [] # a list of all the Thread objects 35 | for i in range(0, 1400, 100): # loops 14 times, creates 14 threads 36 | downloadThread = threading.Thread(target=downloadXkcd, args=(i, i + 99)) 37 | downloadThreads.append(downloadThread) 38 | downloadThread.start() 39 | 40 | # Wait for all threads to end. 41 | for downloadThread in downloadThreads: 42 | downloadThread.join() 43 | print('Done.') 44 | -------------------------------------------------------------------------------- /18-GUI-control/formFiller.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # formFiller.py - Automatically fills in the form. 3 | 4 | import pyautogui, time 5 | 6 | # Set these to the correct coordinates for your particular computer. 7 | nameField = (648, 319) 8 | submitButton = (651, 817) 9 | submitButtonColor = (75, 141, 249) 10 | submitAnotherLink = (760, 224) 11 | 12 | formData = [{'name': 'Alice', 'fear': 'eavesdroppers', 'source': 'wand', 'robocop': 4, 'comments': 'Tell Bob I said hi.'}, 13 | {'name': 'Bob', 'fear': 'bees', 'source': 'amulet', 'robocop': 4, 'comments': 'n/a'}, 14 | {'name': 'Carol', 'fear': 'puppets', 'source': 'crystal ball', 'robocop': 1, 'comments': 'Please take the puppets out of the break room.'}, 15 | {'name': 'Alex Murphy', 'fear': 'ED-209', 'source': 'money', 'robocop': 5, 'comments': 'Protect the innocent. Serve the public trust. Uphold the law.'}, 16 | ] 17 | 18 | pyautogui.PAUSE = 0.5 19 | 20 | for person in formData: 21 | # Give the user a chance to kill the script. 22 | print('>>> 5 SECOND PAUSE TO LET USER PRESS CTRL-C <<<') 23 | time.sleep(5) 24 | 25 | # Wait until the form page has loaded. 26 | while not pyautogui.pixelMatchesColor(submitButton[0], submitButton[1], submitButtonColor): 27 | time.sleep(0.5) 28 | 29 | print('Entering %s info...' % (person['name'])) 30 | pyautogui.click(nameField[0], nameField[1]) 31 | 32 | # Fill out the Name field. 33 | pyautogui.typewrite(person['name'] + '\t') 34 | 35 | # Fill out the Greatest Fear(s) field. 36 | pyautogui.typewrite(person['fear'] + '\t') 37 | 38 | # Fill out the Source of Wizard Powers field. 39 | if person['source'] == 'wand': 40 | pyautogui.typewrite(['down', '\t']) 41 | elif person['source'] == 'amulet': 42 | pyautogui.typewrite(['down', 'down', '\t']) 43 | elif person['source'] == 'crystal ball': 44 | pyautogui.typewrite(['down', 'down', 'down', '\t']) 45 | elif person['source'] == 'money': 46 | pyautogui.typewrite(['down', 'down', 'down', 'down', '\t']) 47 | 48 | # Fill out the Robocop field. 49 | if person['robocop'] == 1: 50 | pyautogui.typewrite([' ', '\t']) 51 | elif person['robocop'] == 2: 52 | pyautogui.typewrite(['right', '\t']) 53 | elif person['robocop'] == 3: 54 | pyautogui.typewrite(['right', 'right', '\t']) 55 | elif person['robocop'] == 4: 56 | pyautogui.typewrite(['right', 'right', 'right', '\t']) 57 | elif person['robocop'] == 5: 58 | pyautogui.typewrite(['right', 'right', 'right', 'right', '\t']) 59 | 60 | # Fill out the Additional comments field. 61 | pyautogui.typewrite(person['comments'] + '\t') 62 | 63 | # Click Submit. 64 | pyautogui.press('enter') 65 | 66 | # Wait until form page has loaded. 67 | print('Clicked Submit.') 68 | time.sleep(5) 69 | 70 | # Click the Submit another response link. 71 | pyautogui.click(submitAnotherLink[0], submitAnotherLink[1]) 72 | -------------------------------------------------------------------------------- /automate_online-materials/formFiller.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # formFiller.py - Automatically fills in the form. 3 | 4 | import pyautogui, time 5 | 6 | # Set these to the correct coordinates for your particular computer. 7 | nameField = (648, 319) 8 | submitButton = (651, 817) 9 | submitButtonColor = (75, 141, 249) 10 | submitAnotherLink = (760, 224) 11 | 12 | formData = [{'name': 'Alice', 'fear': 'eavesdroppers', 'source': 'wand', 'robocop': 4, 'comments': 'Tell Bob I said hi.'}, 13 | {'name': 'Bob', 'fear': 'bees', 'source': 'amulet', 'robocop': 4, 'comments': 'n/a'}, 14 | {'name': 'Carol', 'fear': 'puppets', 'source': 'crystal ball', 'robocop': 1, 'comments': 'Please take the puppets out of the break room.'}, 15 | {'name': 'Alex Murphy', 'fear': 'ED-209', 'source': 'money', 'robocop': 5, 'comments': 'Protect the innocent. Serve the public trust. Uphold the law.'}, 16 | ] 17 | 18 | pyautogui.PAUSE = 0.5 19 | 20 | for person in formData: 21 | # Give the user a chance to kill the script. 22 | print('>>> 5 SECOND PAUSE TO LET USER PRESS CTRL-C <<<') 23 | time.sleep(5) 24 | 25 | # Wait until the form page has loaded. 26 | while not pyautogui.pixelMatchesColor(submitButton[0], submitButton[1], submitButtonColor): 27 | time.sleep(0.5) 28 | 29 | print('Entering %s info...' % (person['name'])) 30 | pyautogui.click(nameField[0], nameField[1]) 31 | 32 | # Fill out the Name field. 33 | pyautogui.typewrite(person['name'] + '\t') 34 | 35 | # Fill out the Greatest Fear(s) field. 36 | pyautogui.typewrite(person['fear'] + '\t') 37 | 38 | # Fill out the Source of Wizard Powers field. 39 | if person['source'] == 'wand': 40 | pyautogui.typewrite(['down', '\t']) 41 | elif person['source'] == 'amulet': 42 | pyautogui.typewrite(['down', 'down', '\t']) 43 | elif person['source'] == 'crystal ball': 44 | pyautogui.typewrite(['down', 'down', 'down', '\t']) 45 | elif person['source'] == 'money': 46 | pyautogui.typewrite(['down', 'down', 'down', 'down', '\t']) 47 | 48 | # Fill out the Robocop field. 49 | if person['robocop'] == 1: 50 | pyautogui.typewrite([' ', '\t']) 51 | elif person['robocop'] == 2: 52 | pyautogui.typewrite(['right', '\t']) 53 | elif person['robocop'] == 3: 54 | pyautogui.typewrite(['right', 'right', '\t']) 55 | elif person['robocop'] == 4: 56 | pyautogui.typewrite(['right', 'right', 'right', '\t']) 57 | elif person['robocop'] == 5: 58 | pyautogui.typewrite(['right', 'right', 'right', 'right', '\t']) 59 | 60 | # Fill out the Additional comments field. 61 | pyautogui.typewrite(person['comments'] + '\t') 62 | 63 | # Click Submit. 64 | pyautogui.press('enter') 65 | 66 | # Wait until form page has loaded. 67 | print('Clicked Submit.') 68 | time.sleep(5) 69 | 70 | # Click the Submit another response link. 71 | pyautogui.click(submitAnotherLink[0], submitAnotherLink[1]) 72 | -------------------------------------------------------------------------------- /automate_online-materials/randomQuizGenerator.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # randomQuizGenerator.py - Creates quizzes with questions and answers in 3 | # random order, along with the answer key. 4 | 5 | import random 6 | 7 | # The quiz data. Keys are states and values are their capitals. 8 | capitals = {'Alabama': 'Montgomery', 'Alaska': 'Juneau', 'Arizona': 'Phoenix', 'Arkansas': 'Little Rock', 'California': 'Sacramento', 'Colorado': 'Denver', 'Connecticut': 'Hartford', 'Delaware': 'Dover', 'Florida': 'Tallahassee', 'Georgia': 'Atlanta', 'Hawaii': 'Honolulu', 'Idaho': 'Boise', 'Illinois': 'Springfield', 'Indiana': 'Indianapolis', 'Iowa': 'Des Moines', 'Kansas': 'Topeka', 'Kentucky': 'Frankfort', 'Louisiana': 'Baton Rouge', 'Maine': 'Augusta', 'Maryland': 'Annapolis', 'Massachusetts': 'Boston', 'Michigan': 'Lansing', 'Minnesota': 'Saint Paul', 'Mississippi': 'Jackson', 'Missouri': 'Jefferson City', 'Montana': 'Helena', 'Nebraska': 'Lincoln', 'Nevada': 'Carson City', 'New Hampshire': 'Concord', 'New Jersey': 'Trenton', 'New Mexico': 'Santa Fe', 'New York': 'Albany', 'North Carolina': 'Raleigh', 'North Dakota': 'Bismarck', 'Ohio': 'Columbus', 'Oklahoma': 'Oklahoma City', 'Oregon': 'Salem', 'Pennsylvania': 'Harrisburg', 'Rhode Island': 'Providence', 'South Carolina': 'Columbia', 'South Dakota': 'Pierre', 'Tennessee': 'Nashville', 'Texas': 'Austin', 'Utah': 'Salt Lake City', 'Vermont': 'Montpelier', 'Virginia': 'Richmond', 'Washington': 'Olympia', 'West Virginia': 'Charleston', 'Wisconsin': 'Madison', 'Wyoming': 'Cheyenne'} 9 | capitalsItems = list(capitals.items()) 10 | 11 | # Generate 35 quiz files. 12 | for quizNum in range(35): 13 | # Create the quiz and answer key files. 14 | quizFile = open('capitalsquiz%s.txt' % (quizNum + 1), 'w') 15 | answerKeyFile = open('capitalsquiz_answers%s.txt' % (quizNum + 1), 'w') 16 | 17 | # Write out the header for the quiz. 18 | quizFile.write('Name:\n\nDate:\n\nPeriod:\n\n') 19 | quizFile.write((' ' * 20) + 'State Capitals Quiz (Form %s)' % (quizNum + 1)) 20 | quizFile.write('\n\n') 21 | 22 | # Shuffle the order of the states. 23 | states = list(capitals.keys()) # get all states in a list 24 | random.shuffle(states) # randomize the order of the states 25 | 26 | # Loop through all 50 states, making a question for each. 27 | for questionNum in range(50): 28 | 29 | # Get right and wrong answers. 30 | correctAnswer = capitals[states[questionNum]] 31 | wrongAnswers = list(capitals.values()) # get a complete list of answers 32 | del wrongAnswers[wrongAnswers.index(correctAnswer)] # remove the right answer 33 | wrongAnswers = random.sample(wrongAnswers, 3) # pick 3 random ones 34 | 35 | answerOptions = wrongAnswers + [correctAnswer] 36 | random.shuffle(answerOptions) # randomize the order of the answers 37 | 38 | # Write the question and answer options to the quiz file. 39 | quizFile.write('%s. What is the capital of %s?\n' % (questionNum + 1, states[questionNum])) 40 | for i in range(4): 41 | quizFile.write(' %s. %s\n' % ('ABCD'[i], answerOptions[i])) 42 | quizFile.write('\n') 43 | 44 | # Write out the answer key to a file. 45 | answerKeyFile.write('%s. %s\n' % (questionNum + 1, 'ABCD'[answerOptions.index(correctAnswer)])) 46 | quizFile.close() 47 | answerKeyFile.close() 48 | -------------------------------------------------------------------------------- /08-file/randomQuizGenerator.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # randomQuizGenerator.py - Creates quizzes with questions and answers in 3 | # random order, along with the answer key. 4 | 5 | import random 6 | import os 7 | 8 | # The quiz data. Keys are states and values are their capitals. 9 | capitals = {'Alabama': 'Montgomery', 'Alaska': 'Juneau', 'Arizona': 'Phoenix', 'Arkansas': 'Little Rock', 'California': 'Sacramento', 'Colorado': 'Denver', 'Connecticut': 'Hartford', 'Delaware': 'Dover', 'Florida': 'Tallahassee', 'Georgia': 'Atlanta', 'Hawaii': 'Honolulu', 'Idaho': 'Boise', 'Illinois': 'Springfield', 'Indiana': 'Indianapolis', 'Iowa': 'Des Moines', 'Kansas': 'Topeka', 'Kentucky': 'Frankfort', 'Louisiana': 'Baton Rouge', 'Maine': 'Augusta', 'Maryland': 'Annapolis', 'Massachusetts': 'Boston', 'Michigan': 'Lansing', 'Minnesota': 'Saint Paul', 'Mississippi': 'Jackson', 'Missouri': 'Jefferson City', 10 | 'Montana': 'Helena', 'Nebraska': 'Lincoln', 'Nevada': 'Carson City', 'New Hampshire': 'Concord', 'New Jersey': 'Trenton', 'New Mexico': 'Santa Fe', 'New York': 'Albany', 'North Carolina': 'Raleigh', 'North Dakota': 'Bismarck', 'Ohio': 'Columbus', 'Oklahoma': 'Oklahoma City', 'Oregon': 'Salem', 'Pennsylvania': 'Harrisburg', 'Rhode Island': 'Providence', 'South Carolina': 'Columbia', 'South Dakota': 'Pierre', 'Tennessee': 'Nashville', 'Texas': 'Austin', 'Utah': 'Salt Lake City', 'Vermont': 'Montpelier', 'Virginia': 'Richmond', 'Washington': 'Olympia', 'West Virginia': 'Charleston', 'Wisconsin': 'Madison', 'Wyoming': 'Cheyenne'} 11 | capitalsItems = list(capitals.items()) 12 | 13 | # Generate 35 quiz files. 14 | for quizNum in range(35): 15 | # Create a directory for storing files. 16 | directory = 'QuizAndAnswers' 17 | if not os.path.exists(directory): 18 | os.mkdir(directory) 19 | 20 | # Create the quiz and answer key files. 21 | quizFile = open('%s/capitalsquiz%s.txt' % (directory, quizNum + 1), 'w') 22 | answerKeyFile = open('%s/capitalsquiz_answers%s.txt' % (directory, quizNum + 1), 'w') 23 | 24 | # Write out the header for the quiz. 25 | quizFile.write('Name:\n\nDate:\n\nPeriod:\n\n') 26 | quizFile.write((' ' * 20) + 'State Capitals Quiz (Form %s)' % 27 | (quizNum + 1)) 28 | quizFile.write('\n\n') 29 | 30 | # Shuffle the order of the states. 31 | states = list(capitals.keys()) # get all states in a list 32 | random.shuffle(states) # randomize the order of the states 33 | 34 | # Loop through all 50 states, making a question for each. 35 | for questionNum in range(50): 36 | 37 | # Get right and wrong answers. 38 | correctAnswer = capitals[states[questionNum]] 39 | # get a complete list of answers 40 | wrongAnswers = list(capitals.values()) 41 | # remove the right answer 42 | del wrongAnswers[wrongAnswers.index(correctAnswer)] 43 | wrongAnswers = random.sample(wrongAnswers, 3) # pick 3 random ones 44 | 45 | answerOptions = wrongAnswers + [correctAnswer] 46 | random.shuffle(answerOptions) # randomize the order of the answers 47 | 48 | # Write the question and answer options to the quiz file. 49 | quizFile.write('%s. What is the capital of %s?\n' % 50 | (questionNum + 1, states[questionNum])) 51 | for i in range(4): 52 | quizFile.write(' %s. %s\n' % ('ABCD'[i], answerOptions[i])) 53 | quizFile.write('\n') 54 | 55 | # Write out the answer key to a file. 56 | answerKeyFile.write('%s. %s\n' % ( 57 | questionNum + 1, 'ABCD'[answerOptions.index(correctAnswer)])) 58 | quizFile.close() 59 | answerKeyFile.close() 60 | -------------------------------------------------------------------------------- /automate_online-materials/torrentStarter.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # Checks for instructions via email and runs them. 3 | # So far, this program checks for BitTorrent "magnet" links and launches the torrent program for them. 4 | 5 | import smtplib, imapclient, pyzmail, logging, traceback, time, subprocess 6 | logging.basicConfig(filename='torrentStarterLog.txt', level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s') 7 | 8 | # Configure the program by setting some variables. 9 | MY_EMAIL = 'asweigart@gmail.com' # bot should only respond to me 10 | BOT_EMAIL = 'imaptest@coffeeghost.net' 11 | BOT_EMAIL_PASSWORD = '7|)6S1JS6>euu8p/nTlf' 12 | IMAP_SERVER = 'mail.coffeeghost.net' 13 | SMTP_SERVER = 'mail.coffeeghost.net' 14 | SMTP_PORT = 465 15 | TORRENT_PROGRAM = 'C:\\Program Files (x86)\\qBittorrent\\qbittorrent.exe' 16 | 17 | assert BOT_EMAIL != MY_EMAIL, "Give the bot it's own email address." 18 | 19 | 20 | def getInstructionEmails(): 21 | # Log in to the email imapCli. 22 | logging.debug('Connecting to IMAP server at %s...' % (IMAP_SERVER)) 23 | imapCli = imapclient.IMAPClient(IMAP_SERVER, ssl=True) 24 | imapCli.login(BOT_EMAIL, BOT_EMAIL_PASSWORD) 25 | imapCli.select_folder('INBOX') 26 | logging.debug('Connected.') 27 | 28 | # Fetch all instruction emails. 29 | instructions = [] 30 | UIDs = imapCli.search(['FROM ' + MY_EMAIL]) 31 | rawMessages = imapCli.fetch(UIDs, ['BODY[]']) 32 | for UID in rawMessages.keys(): 33 | # Parse the raw email message. 34 | message = pyzmail.PyzMessage.factory(rawMessages[UID]['BODY[]']) 35 | if message.html_part != None: 36 | body = message.html_part.get_payload().decode(message.html_part.charset) 37 | if message.text_part != None: 38 | # If there's both an html and text part, use the text part. 39 | body = message.text_part.get_payload().decode(message.text_part.charset) 40 | 41 | # Extract instruction from email body. 42 | instructions.append(body) 43 | 44 | # Delete the instruction emails, if there are any. 45 | if len(UIDs) > 0: 46 | imapCli.delete_messages(UIDs) 47 | imapCli.expunge() 48 | 49 | imapCli.logout() 50 | 51 | return instructions 52 | 53 | 54 | def parseInstructionEmail(instruction): 55 | # Send an email response about the task. 56 | responseBody = 'Subject: Instruction completed.\nInstruction received and completed.\nResponse:\n' 57 | 58 | # Parse the email body to figure out the instruction. 59 | lines = instruction.split('\n') 60 | for line in lines: 61 | if line.startswith('magnet:?'): 62 | subprocess.Popen(TORRENT_PROGRAM + ' ' + line) # launch the bittorrent program 63 | responseBody += 'Downloading magnet link.\n' 64 | 65 | # Email the response body to confirm the bot carried out this instruction. 66 | logging.debug('Connecting to SMTP server at %s to send confirmation email...' % (SMTP_SERVER)) 67 | #smtpCli = smtplib.SMTP(SMTP_SERVER, SMTP_PORT) # uncomment one or the other as needed. 68 | smtpCli = smtplib.SMTP_SSL(SMTP_SERVER, SMTP_PORT) # uncomment one or the other as needed. 69 | smtpCli.ehlo() 70 | #smtpCli.starttls() # comment this out if using SMTP_SSL 71 | smtpCli.login(BOT_EMAIL, BOT_EMAIL_PASSWORD) 72 | logging.debug('Connected.') 73 | smtpCli.sendmail(BOT_EMAIL, MY_EMAIL, responseBody) 74 | logging.debug('Confirmation email sent.') 75 | smtpCli.quit() 76 | 77 | 78 | # Start an infinite loop that checks email and carries out instructions. 79 | print('Email bot started. Press Ctrl-C to quit.') 80 | logging.debug('Email bot started.') 81 | while True: 82 | try: 83 | logging.debug('Getting instructions from email...') 84 | instructions = getInstructionEmails() 85 | for instruction in instructions: 86 | logging.debug('Doing instruction: ' + instruction) 87 | parseInstructionEmail(instruction) 88 | except Exception as err: 89 | logging.error(traceback.format_exc()) 90 | 91 | # Wait 15 minutes before checking again 92 | logging.debug('Done processing instructions. Pausing for 15 minutes.') 93 | time.sleep(60 * 15) 94 | --------------------------------------------------------------------------------