I know the main question is simple sounding, but I am specifically trying to iterate a whole CSV to find a certain variable while maintaining all the other columns connected to it. I am trying to create a file that essentially checks a certain date and then emails reminders or other templates to a list of students that qualify (based on the date or course) for the reminders. Currently with my code, I can't figure a way to keep the variables linked. I can get a list of students that I want to email, but am having trouble with the names staying linked to the emails I want.
import pandas as pd
import datetime as dt
from datetime import timedelta
import os
from email.message import EmailMessage
df = pd.read_excel('Students.xlsx')
EMAIL_ADDRESS = os.environ.get('EMAIL_USER')
EMAIL_PASSWORD = os.environ.get('EMAIL_PASS')
MAIL_LIST = ''
STUDENT_MAIL = df.student_email
DUE_DATE = df.course_completion_date
COURSE = df.course_section
START_DATE = dt.date.today()
END_DATE = START_DATE + timedelta(days=6)
I then have my codes for basic templates which I have tested and used prior so I know work.
But then I have tried several loops to try and add student emails to it through a loop so for example I would want all students finishing within a week to receive an email
for date in DUE_DATE:
if START_DATE <= date <= END_DATE:
MAIL_LIST = MAIL_LIST + STUDENT_EMAIL
else:
Now I know this looks dumb but this was just my last attempt at trying to get it to work. But I have tried several other ways to get it to work but the problem I run into is that the for loop has to be a single column to make a list it can check against but I need it connected to the second column of their emails to make the mailing list. Am I overcomplicating this I feel like I'm kind of going crazy
Using the DataFrame already will keep the variables linked like you would for index in rows and columns.
If you are trying to just grab the row matching the email you can use .loc to find the matching row for students to emails.
something like:
df.loc[x]['MAIL_LIST']
pandas.DataFrame.loc
Related
I'm recieving date in PMS message something like this |GA090616|GD090617|
which means Guest Arrival is at 09-06-16 and Guest Deprature is at 09-06-17
I wanted to parse it as date using python.
I've also visited stack oveflow[1, 2 ...] for this but as solution I've found
from datetime import datetime
self.DATE_FROMAT='%d/%m/%y'
arrival_date=datetime.strptime('90616', self.DATE_FROMAT).date()
print(arrival_date)
and it's not possible to parse it like this due to its unclear format.
I'm not sure if 09 is a month or a date, but from what I've seen in documents and PDFs, it appears to be a month.
Is there any better solution for this kind of date parsing? or suggestions for my expectations.
09-06-16,
09-06-17
Note:
Please Just take the date from the string 090617 and parse it as a date. That will be helpful.
You can do this with regex matching, you can either split the string with msg.split("|") or not, but that depends on your use case.
import re
from datetime import datetime
msg = "GA090616|GD090617|"
DATE_FORMAT='%d%m%y'
ar = re.match("GA(\d{6})", msg)
dp = re.match("GD(\d{6})", msg)
guest_arrival = datetime.strptime(ar.group(1), DATE_FORMAT).date()
guest_departure = datetime.strptime(dp.group(1), DATE_FORMAT).date()
Although not fully tested, this should be a boilerplate as to how to retrieve the date from the message. Remember to remove the \ from the date format, as that is not included in the message.
This func is for Year alone. (Doesn't work)
def daterange(args):
user_inp = datetime.strptime(args,'%Y')
rmail = object.Restrict("[ReceivedTime] == '" + user_inp.strftime('%Y')+"'")
return rmail
The Restrict code doesn't work with = , throws error with == and only works with >=
My requirement is all mails from user_inp(2020) or 2019 etc
Please Help !!!
The Restrict code doesn't work with = , throws error with == and only works with >=
Using the equal operator is not really a good idea. Instead, you need to specify the time and date range. The difference can be a minute, but not equal.
Read more about the date and time comparisons in Outlook on the Filtering Items Using a Date-time Comparison page.
I am building a scraper that searches reddit comments for keywords. I am having two problems
Problem 1. in order to build the commentforest I need to get the submission_id from the comment so I can pull all of the comments related to that submission.I am having trouble figuring out how to get the submission id.
problem 2. for some reason every time I run this code it gives me new comments that include the keywords (I am assuming this is just because new comments have been added) BUT some of the old comments arent showing up when i run the code again. this is supposed to pull ALL the comments that match my keyword from the subreddit what am i doing wrong?
from psaw import PushshiftAPI
from datetime import datetime, timezone, timedelta
from dateutil.relativedelta import relativedelta
api = PushshiftAPI()
comments = api.search_comments(q='OP', subreddit='askreddit')
max_response_cache = 1000
cache = []
commentcount = 0
for c in comments:
cache.append(c)
commentcount += 1
print (f' comment {commentcount}: {c.body}')
I want the code to print out the submission id related to the comments and I want to be able to pull all the comments that match my keywords.
I'm using Python 3.
I'm trying to extract (list / print show) outlook emails by date.
I was trying a loop.. maybe WHILE or IF statement.
Can it be done since ones a string and the other is a date.
Please concide what I've got so far: Thanks.
1. import win32com.client, datetime
2.
3. # Connect with MS Outlook - must be open.
4. outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
5. # connect to Sent Items
6. sent = outlook.GetDefaultFolder(5).Items # "5" refers to the sent item of a folder
7.
8. # Get yesterdays date
9. y = (datetime.date.today () - datetime.timedelta (days=1))
10. # Get emails by selected date
11. if sent == y:
12. msg = sent.GetLast()
13. # get Subject line
14. sjl = msg.subject
14. # print it out
15. print (sjl)
Ive completed the code. Thanks for help.
`import sys, win32com.client, datetime
# Connect with MS Outlook - must be open.
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace
("MAPI")
# connect to Sent Items
s = outlook.GetDefaultFolder(5).Items # "5" refers to the sent item of a
folder
#s.Sort("s", true)
# Get yesterdays date for the purpose of getting emails from this date
d = (datetime.date.today() - datetime.timedelta (days=1)).strftime("%d-%m-%
y")
# get the email/s
msg = s.GetLast()
# Loop through emails
while msg:
# Get email date
date = msg.SentOn.strftime("%d-%m-%y")
# Get Subject Line of email
sjl = msg.Subject
# Set the critera for whats wanted
if d == date and msg.Subject.startswith("xx") or msg.Subject.startswith
("yy"):
print("Subject: " + sjl + " Date : ", date)
msg = s.GetPrevious() `
This works. However if no message according to the constraint if found, it doesnt exit. Ive tried break which just finds one message and not all, Im wondering if and how to do an exception? or if i try a else d != date it doenst work either (it will not find anything).
I cant see that a For loop will work using a date with a msg(string).
I not sure -- biginner here :)
??
The outlook API has a method, Items.Find, for searching the contents of .Items. If this is the extent of what you want to do, that's probably how you should do it.
Right now it seems like your if statement is checking whether set of emails is equal to yesterday.
Microsoft's documentation says .Items is returning a collection of emails which you first must iterate through using a few different methods including Items.GetNext or by referencing a specific index with Items.Item.
You can then take the current email and access the .SentOn property.
currentMessage = sent.GetFirst()
while currentMessage:
if currentMessage.SentOn == y:
sjl = currentMessage.Subject
print(sjl)
currentMessage = sent.GetNext()
This should iterate through all messages in the sent folder until sent.GetNext() has no more messages to return. You will have to make sure y is the same formatting as what .SentOn returns.
If you don't want to iterate through every message, you could probably also nest two loops that goes back in messages until it gets to yesterday, iterates until it is no longer within "yesterday", and then breaks.
The COM API documentation is fairly thorough, you can see the class list for example here. It also documents the various methods you can use to manipulate the objects it has. In your particular example what you are after is to restrict your set of items via date. You will see that there is already a function for that in the items class here. Conveniently it is called Restrict. The only gotcha I can see with that function is that you need to specify the filter that you would like on your items in string form, thus requiring you to construct the string yourself.
So for example to continue your code and restrict by time:
#first create the string filter, here you would like to filter on sent time
#assuming you wanted emails after 5 pm as an example and your date d from the code above
sFilter = "[SentOn] > '{0} 5:00 PM'".format(d)
#then simply retrieve your restricted items
filteredEmails = s.Restrict(sFilter)
You can of course restrict by all sorts of criteria, just check the documentation on the function. This way if you restrict and it returns an empty set of items you can handle that case in the code rather than having to work with exceptions. So for example:
#you have restricted your selection now want to check if you have anything
if filteredEmails.Count == 0:
#handle this situation however you would like
Is it possible to use the created_at filter as part of a query in Python? I added it into my query filters, trying several different ways, but it seems to ignore that particular filter. The results that come back contain everything from last week to 3 years ago, and I'm only looking for recent tracks. I have to believe this is doable somehow...
stamp = "2013/07/01 09:24:50 +0000"
tracks = client.get('/tracks', q='Metallica', genre='', duration={
'from': 1800000
}, created_at={
'from': stamp
}, limit='5', tags='Metal')
I've also tried just entering the datetime stamp directly instead of as a variable, with the same results. Am I just botching the code somewhere here? Or can you really not specify the created_at date for your query results?
Yes! It is possible to use the created_at filter as part of a query in Python.
I do not know how the SoundCloud API prioritizes each of the filters, so it is possible that adding more filters may lead to unexpected results.
Limiting the filters simply to the filters {query, created_at} yield your desired result.
# https://github.com/soundcloud/soundcloud-python
import soundcloud
# Authentication
CLIENT_ID = 'insert_client_id_here'
client = soundcloud.Client(client_id=CLIENT_ID)
# Call GET request with parameters
# excludes: {genres,tags,duration}
# includes: {order,limit} for organization
stamp = "2013/07/01 09:24:50 +0000"
tracks = client.get('/tracks',
q='Metallica',
created_at= {'from': stamp},
order='created_at',
limit=5,
)
# Print the results
for i, v in enumerate(tracks):
print i, v.title, v.created_at