Tweepy: Rotate API object in the middle of Cursor iteration - python

So basically I'm trying to obtain the followers of a user with many of them. I'm using tweepy for this and I can't simply wait the 60 seconds every time I hit the limit or this will take too long. So this is my approach, to me it makes sense as it s keeping track of next_cursor (which is initialized as -1):
while getting_followers:
try:
follower_cursors = tweepy.Cursor(api.followers_ids, id=userid, next_cursor=current_cursor)
for follower_cursor in follower_cursors.pages():
temp_list = temp_list + follower_cursor
print "Getting Followers..."
getting_followers = False
except Exception as e:
print "Error obtaining node followers"
print e
if str(e) == "Not authorized.":
print "Not authorized, skipping.", str(userid)
getting_followers = False
elif str(e) == "[{'message': 'Sorry, that page does not exist.', 'code': 34}]":
print e
getting_followers = False
else:
print "Changing accounts."
api = rotateAccounts()
current_cursor = follower_cursors.iterator.next_cursor
the problem is this doesn't work, the Cursor restarts every time I rotate api, it doesn't remember the current cursor

Related

Python How to do an while statement with multiple tries then loop

Python - I am trying to get some code to check whether a webpage has loaded correctly, and handle a couple of exception (but not error) scenarios.
So the code would do the following
While the webpage is not loaded correctly (I have set some variables to control this)
try to check whether the page had loaded correctly
try to check whether it hasn't loaded correctly as the account is logged out
try to check whether it hasn't loaded correctly as it needs an update
otherwise wait 5 seconds and loop through the block again, until the maximum number of retries has been hit
I tried doing Try, except, except but as the errors are not specific (TypeError etc) then I get an 'Only one catch all' code rejection
I also considered an If Elif etc but then I don't know how to get it to loop back to the start if it doesn't match any of the scenarios and needs to wait and then try again.
The code I have tried
while not loaded and attempts < maxattempts and not loggedout: #confirm that the page is not loaded, not too many attempts or logged out.
try:
x1, y1=pygu.center(pygu.locateOnScreen("/whatsappopened.png", confidence=0.8))
time.sleep(2)
pygu.moveTo(x1,y1)
current_time = now.strftime("%H-%M-%S")
loaded =True
except:
x1, y1=pygu.center(pygu.locateOnScreen("whatsapploggedout.png", confidence=0.8))
time.sleep(2)
pygu.moveTo(x1,y1)
loggedout =True
except:
x1, y1=pygu.center(pygu.locateOnScreen("/whatsappupdate.png", confidence=0.8))
time.sleep(2)
pygu.hotkey('ctrl', 'w')
loggedout =True
except:
time.sleep(5)
attempts += +1
print("page not loaded after %s attempts" %(attempts))
Any guidance appreciated!
I came up with a potential solution with comments that may let you think about how to continue with the program and suit it to your needs.
attempts = 1
maxattempts = 5
loaded = False
loggedout = False
update = False
time_now = datetime.now()
while not loaded and attempts < maxattempts and not loggedout: #confirm that the page is not loaded, not too many attempts or logged out.
# Check if WhatsApp is open
try:
x1, y1=pygu.center(pygu.locateOnScreen("whatsappopened.png", confidence=0.8))
print("WhatsApp opened")
time.sleep(2)
pygu.moveTo(x1, y1)
time_now = datetime.now().strftime("%H:%M:%S")
loaded = True
except Exception as e:
# Here because WhatsApp is not open or logged out
# Check if WhatsApp is logged out
try:
x2, y2=pygu.center(pygu.locateOnScreen("whatsapploggedout.png", confidence=0.8))
print("WhatsApp logged out")
time.sleep(2)
pygu.moveTo(x2, y2)
loggedout = True
except Exception as e:
# Check if needs update
try:
x3, y3=pygu.center(pygu.locateOnScreen("whatsappupdate.png", confidence=0.8))
print("WhatsApp update")
time.sleep(2)
pygu.moveTo(x3, y3)
update = True
except Exception as e:
# Not open
print("WhatsApp not open")
time.sleep(2)
attempts += 1
time_now = datetime.now().strftime("%H:%M:%S")
loaded = False
loggedout = False
update = False
print("Attempts: " + str(attempts))

How to repeat a step in a loop if an action fails?

In the case I am looping into a list, where for value msg_list = 0 it will execute action(0), usr). This action can fail for a determined user, I should choose aother user if it happens, perform all the actions related to the user
How can I do to repeat action[0] if it fails?
for msg in range(len(msg_list)):
# in this case msg = 0
usr = select_random_user()
multiple_actions_for(usr) # This are lots of code lines I don't want to repeat!!
try:
action(msg, usr)
more_actions(usr.related_stuff)
except Exception as e:
go_back_to(msg =0 instead of looping into msg=1) # this is what I want to do
How can I do to get that? Repeat the loop for msg = i instead of passing to msg = i + 1?
Put your code into the endless while-loop with exiting from it if try was successful:
for msg in range(len(msg_list)):
while True:
usr = select_random_user()
multiple_actions_for(usr)
try:
action(msg, usr)
more_actions(usr.related_stuff)
except Exception as e:
continue
else:
break
It really depends. Is it okay to go back to the beginning of the loop? If so, you can call "continue", which stops the current iteration, and restarts the loop. Otherwise, I don't think there's something similar to a goto in Python, no. It's a very structured language.
Try using while loop instead of for loop. The idea is as shown bellow:
bool still_looping = True
msg = 0
while still_looping:
usr = select_random_user()
multiple_actions_for(usr)
try:
action(msg, usr)
more_actions(usr.related_stuff)
if (msg < len (msg_list)):
msg += 1
except Exception as e:
# Do whatever you want here. msg was not incremented
if (msg == len(msg_list))
still_looping = False #verify if this was the last execution

My code wont fully run through my dictionary and i cant figure out why

I am new to coding and have been trying to write an automated email formater and sender but am running into trouble trying to get it to realise when it has already sent someone an email.
I tried using a searchable dictionary as shown in the code below however once it sends one email it stops due to something in the code.
This is only a segment of a class for the full code please ask.
def send_email(self):
self.message_format()
if len(self.messages) > 0:
for i in self.messages:
user_email = self.messages[i]["email"]
user_msg = self.messages[i]["message"]
if i in self.sent_to_list:
return False
else:
try:
email_conn = smtplib.SMTP(host,port)
email_conn.ehlo()
email_conn.starttls()
email_conn.login(username, password)
the_msg = MIMEMultipart("alternative")
the_msg["Subject"] = "Hello there!"
the_msg["From"] = from_email
the_msg["To"] = user_email
right_msg = MIMEText(user_msg, "plain")
the_msg.attach(right_msg)
email_conn.sendmail(from_email, [user_email], the_msg.as_string())
email_conn.quit()
self.sent_to_list[str(i)] = self.messages[i]
except smtplib.SMTPException:
print("Error sending message")
except smtplib.SMTPAuthenticationError:
print("An error occured during login")
return True
return False
When your function executes return statement, it immediately stops and returns the value you wrote in return. So in your function it will stop after the first iteration (because of return True in the pre-last line). If you want your function to work more or less correctly, you should:
Replace the first return False with continue. It will skip every bad message. Moreover, because of this you will not need else. You can just have your code to work.
Remove two last lines. return True because you need to iterate through all messages, return False because it has nearly no sense.
Here is the final code:
def send_email(self):
self.message_format()
if len(self.messages) > 0:
for i in self.messages:
user_email = self.messages[i]["email"]
user_msg = self.messages[i]["message"]
if i in self.sent_to_list:
continue
try:
email_conn = smtplib.SMTP(host,port)
email_conn.ehlo()
email_conn.starttls()
email_conn.login(username, password)
the_msg = MIMEMultipart("alternative")
the_msg["Subject"] = "Hello there!"
the_msg["From"] = from_email
the_msg["To"] = user_email
right_msg = MIMEText(user_msg, "plain")
the_msg.attach(right_msg)
email_conn.sendmail(from_email, [user_email], the_msg.as_string())
email_conn.quit()
self.sent_to_list[str(i)] = self.messages[i]
except smtplib.SMTPException:
print("Error sending message")
except smtplib.SMTPAuthenticationError:
print("An error occured during login")
If I understand it correctly you want to send emails to everyone in the dictionary self.messages unless you have already sent it. Currently you call return after one iteration, which terminates the function.
To handle cases where you have already sent an email use continue which simple jumps to the next iteration. You should also remove the return True since it will terminate the function. If you want a boolean return value it should be false only if there are no messages in self.messages, otherwise it doesn't really make sense. The code would then be.
def send_email(self):
self.message_format()
if len(self.messages) > 0:
for i in self.messages:
user_email = self.messages[i]["email"]
user_msg = self.messages[i]["message"]
if i in self.sent_to_list:
continue
try:
email_conn = smtplib.SMTP(host,port)
email_conn.ehlo()
email_conn.starttls()
email_conn.login(username, password)
the_msg = MIMEMultipart("alternative")
the_msg["Subject"] = "Hello there!"
the_msg["From"] = from_email
the_msg["To"] = user_email
right_msg = MIMEText(user_msg, "plain")
the_msg.attach(right_msg)
email_conn.sendmail(from_email, [user_email], the_msg.as_string())
email_conn.quit()
self.sent_to_list[str(i)] = self.messages[i]
except smtplib.SMTPException:
print("Error sending message")
except smtplib.SMTPAuthenticationError:
print("An error occured during login")
return True
return False
I realise now that my error was in the function I iterate at the top of that function.
def message_format(self):
if len (self.user_details) > 0:
for details in self.get_details():
name = details["name"]
date = details["date"]
total = details["total"]
finished_msg = self.base_message.format(
name = name,
date = date,
total = total
)
user_email = details.get("email")
if user_email:
user_data = {"email": user_email,
"message": finished_msg
}
self.messages["customer_" + str(len(self.messages)+1)] = user_data
return self.messages
else:
return ["No user data given"]

Python - How to loop until site is down using requests and threads

So what I want to do is that I want to make a sorts of monitor a website that pick ups a random number. Before it does it needs to requests to the website to see whenever it is valid or not. When it is live it will generate random numbers 1-100 and I want it to check every random 3-6 second and then print again the number and repeat until the website is down.
What I have tried to do is following:
def get_product_feed(url_site):
thread = url_site
password = False #We start by giving a false/true value
while not password: #If it is not True then we do the for loop
available = False
while not available:
try:
checkpass = requests.get(thread, timeout=12) #We requests the site to see if its alive or not
if ('deadsite' in checkpass.url): #If it contains etc deadsite then we enter the while True
while True:
contcheck = requests.get(thread,timeout=12) #We make new requests to see if its dead.
if ('deadsite' in contcheck.url): #if it is, then we sleep 3-7sec and try again
randomtime = random.randint(3, 7)
time.sleep(randomtime)
else: #If its not containig it anymore then we send the bs4 value
available = True
bs4 = soup(contcheck.text, 'lxml')
return bs4
break
else: #If its having either of them then we send instant.
bs4 = soup(contcheck.text, 'lxml')
return bs4
break
except Exception as err:
randomtime = random.randint(1, 2)
time.sleep(randomtime)
continue
def get_info(thread):
while True:
try:
url = thread
resp = requests.get(url, timeout=12) #We requests to the website here
resp.raise_for_status()
json_resp = resp.json() #We grab the json value.
except Exception as err:
randomtime = random.randint(1,3)
time.sleep(randomtime)
continue
metadata = json_resp['number'] #We return the metadata value back to get_identifier
return metadata
def get_identifier(thread):
new = get_info(thread) #We requests the get_info(thread):
try:
thread_number = new
except KeyError:
thread_number = None
identifier = ('{}').format(thread_number) #We return back to script
return identifier
def script():
url_site = 'https://www.randomsitenumbergenerator.com/' #What url we gonna use
old_list = []
while True:
for thread in get_product_feed(url_site): #We loop to see through get_product_feed if its alive or not
if get_identifier(thread) not in old_list: # We then ask get_identifier(thread) for the values and see if its in the old_list or not.
print(get_identifier(thread)
old_list.append(get_identifier(thread)
I added a comment to make it easier to understand what is going on.
The issue I am having now that I am not able to make get_identifier(thread) to run until the website is down and I want it to continue to print out until the website is live til it dies and that is my question! What do I need to do to make it happen?
My thoughts was to add eventually threads maybe that 10 threads are checking at the same time to see if the website is dead or not and give back the value as a print but I am not sure if that is my solution for the question.

Calling a function within a function within a class

So there's this website that posts something I want to buy at a random time of day for a limited amount of time and I want to write something to send a message to my phone when a new url is posted to that webpage.
I planned on doing this by counting the number of links on the page (since it's rarely updated) and checking it every 5 minutes against what it was 5 minutes before that, then 5 minutes later check it against what it was 10 minutes before that, 5 minutes later check what it was 15 minutes before that... and if it's greater than what it originally was, send a message to my phone. Here's what I have so far:
class url_alert:
url = ''
def link_count(self):
notifyy=True
while notifyy:
try:
page = urllib.request.urlopen(self.url)
soup = bs(page, "lxml")
links=[]
for link in soup.findAll('a'):
links.append(link.get('href'))
notifyy=False
print('found', int(len(links)), 'links')
except:
print('Stop making so many requests')
time.sleep(60*5)
return len(links)
def phone(self):
self= phone
phone.message = client.messages.create(to="", from_="",body="")
print('notified')
def looper(self):
first_count = self.link_count()
print('outside while')
noty = True
while noty:
try:
second_count = self.link_count()
print('before compare')
if second_count == first_count:
self.phone()
noty = False
except:
print('not quite...')
time.sleep(60)
alert = url_alert()
alert.looper()
As a test, I decided to set the if statement that determines whether or not to send a message as equal but the loop kept on running. Am I calling the functions within the looper function the right way?
It looks like you need to eliminate the try block, as it is now, if self.phone() takes an exception you will never leave the loop
def looper(self):
first_count = self.link_count()
while True:
if first_count != self.link_count():
self.phone()
break
time.sleep(60)

Categories

Resources