im using Selenium and Python to create a Whatsapp Bot to read number and name from xlsx file and send specific message!
started by webdriver.
open web.whatsapp.com and use parameters from excel file to send a message.
Code is HERE :
def readContacts(fileName):
delay = 30
f = open("message.txt", encoding='utf-8')
ads = f.read()
f.close()
ads = quote(ads)
lst = []
file = excel.load_workbook(fileName)
sheet = file.active
firstCol = sheet['A']
secondCol = sheet['B']
driver = webdriver.Chrome(ChromeDriverManager().install())
driver.get('https://web.whatsapp.com')
time.sleep(1)
for cell in range(len(firstCol)):
contact = str(firstCol[cell].value)
message = str(secondCol[cell].value)
link = "https://web.whatsapp.com/send?phone="+ contact +"&text="+ message + ' عزیز ' + '%0A ' + ads
driver.get(link)
print("Sending message to", contact)
try:
click_btn = WebDriverWait(driver, delay).until(EC.element_to_be_clickable((By.CLASS_NAME , '_4sWnG')))
click_btn.click()
sleep(5)
print("Message sent successfuly")
except NoSuchElementException:
print("Failed to send message")
driver.quit()
targets = readContacts("./contact.xlsx")
now i have numbers in excel file that are not member of whatsapp.
how can i skip this number?
Related
def send_unsaved_contact_message():
global message
try:
time.sleep(10)
browser.implicitly_wait(10)
#input_box = (By.XPATH,"//div[text()='Type a message']")
#input_box = (By.XPATH,"//div[#class='p3_M1']")
input_box = WebDriverWait(browser, 20).until(EC.presence_of_element_located((By.CSS_SELECTOR,
"p[class='selectable-text copyable-text']")))
pyperclip.copy(message) # get text in clipboard
for ch in message:
if ch == "\n":
ActionChains(browser).key_down(Keys.SHIFT).key_down(Keys.ENTER).key_up(Keys.ENTER).key_up(
Keys.SHIFT).key_up(Keys.BACKSPACE).perform()
else:
input_box.send_keys(ch)
input_box.send_keys(Keys.CONTROL,"v")
#browser.execute_script(JS_ADD_TEXT_TO_INPUT, elem, text)
whatsapp_send_button = browser.find_element(By.XPATH,
"/html[1]/body[1]/div[1]/div[1]/div[1]/div[4]/div[1]/footer[1]/div[1]/div[1]/span[2]/div[1]/div[2]/div[2]/button[1]/span[1]")
browser.execute_script("arguments[0].click();", whatsapp_send_button)
except Exception as e:
print("Failed to send message exception: ", e)
return
for example this is my message:
🌸 Hello everyone🌸
welcome to my group
Group link:
Thank you for visiting our site:
but send in input message like this:
� Hello everyone�
welcome to my group
Group link:
Thank you for visiting our site:
🌸 Hello everyone🌸
welcome to my group
Group link:
Thank you for visiting our site:
you can replace with
js_send_text = """
function send_text(text) {
const dataTransfer = new DataTransfer();
dataTransfer.setData('text', text);
const event = new ClipboardEvent('paste', {
clipboardData: dataTransfer,
bubbles: true
});
let el = document.querySelector('#main .copyable-area [contenteditable="true"][role="textbox"]')
el.dispatchEvent(event)
}
send_text(arguments[0])
"""
self.driver.execute_script(js_send_text, message)
and to check if finish typing can use:
old = ''
while True:
element = self.driver.find_element(By.CSS_SELECTOR,
'#main .copyable-area [contenteditable="true"][role="textbox"]')
if element.text == old:
break
sleep(1)
old = element.text
send button:
self.driver.execute_script("""document.querySelector('[data-testid="send"]').click()""")
I have this script to get the bids of an NFT as they come in, It worked perfectly before however all of a sudden it stopped being able to find the information that i needed.
It was able to save the information into a file and then post the message onto discord
however now it cant get there due to it not being able to get the information.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options
import asyncio,calendar,discord
import time
from discord.ext import commands
TOKEN = "token here"
url = "https://auction.chimpers.xyz/"
class_names = ["m-bid-amount","m-bid-bidder","m-bid-timestamp","m-countdown-pending","m-name",'img']
bot = bot = commands.Bot(command_prefix="!")
channel_id = channel_id here
async def message_on_bid(auction_status="New Bid Placed",bid="has recieved a bid of",bought="from"):
await bot.wait_until_ready()
channel = bot.get_channel(channel_id)
with open("CurrentTopBidder.txt","r") as f:
info = [line.rstrip() for line in f.readlines()]
if len(info[1]) > 10:
info[1] = info[1][:-(len(info[1])-4):] + "..." + info[1][len(info[1])-4::]
myEmbed = discord.Embed(title=auction_status,url="https://auction.chimpers.xyz/",description=f"{info[4]} {bid} Ξ{info[0][:-4]} {bought} {info[1]}",color=0x202020)
myEmbed.set_footer(text=f"{info[2]}")
myEmbed.set_thumbnail(url=info[5])
await channel.send(embed=myEmbed)
async def main():
start_time = time.time()
while True:
if time.time() - start_time > 60:
await message_on_bid(auction_status="Auction Closed",bid="has been bought for",bought="by")
print("auction closed")
with open("CurrentTopBidder.txt","w") as f:
f.write("0 ETH\nOwner\nTime\nAuctionStatus\nName\nimage")
f.close()
break
driver_options = Options()
driver_options.add_argument("--headless")
driver = webdriver.Chrome("Drivers\Chromedriver.exe")
driver.get(url)
results = {}
try:
for class_name in class_names:
if class_name != "img":
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CLASS_NAME, class_name)))
# Getting inner text of the html tag
results[class_name] = element.get_attribute("textContent")
else:
element = WebDriverWait(driver,10).until(EC.presence_of_element_located((By.TAG_NAME,class_name)))
results[class_name] = element.get_attribute("src")
finally:
driver.quit()
print(results)
this_list = []
f = open("CurrentTopBidder.txt","r")
for line in f.readlines():
this_list.append(line.rstrip())
if results["m-name"] == "Unnamed":
results["m-name"] = this_list[4]
if float(results["m-bid-amount"][:-4:]) > float(this_list[0][:-4:]):
if results["m-countdown-pending"] == " Auction ended ":
status = "AuctionEnded"
else:
status = "CurrentTopBidder"
f = open("CurrentTopBidder.txt","w")
f.write(str(results["m-bid-amount"]) + "\n" + str(results["m-bid-bidder"] + "\n" + str(results["m-bid-timestamp"]) + "\n" + str(status) + "\n" + str(results["m-name"]) + "\n" + results["img"]))
f.close()
await message_on_bid()
else:
f.close()
driver.quit()
await asyncio.sleep(600)
if __name__ == "__main__":
bot.loop.create_task(main())
bot.run(TOKEN)
any reason as to why this stopped being able to find the information????
error here
I am using imap_tools to get links from emails. The emails are very small with very little text, graphics, etc. There are also not many, around 20-40 spread through the day.
When a new email arrives it takes between 10 and 25 seconds to scrape the link. This seems very long. I would have expected it to be less than 2 seconds and speed is important.
Nb. it is a shared mailbox and I cannot simply fetch unseeen emails because often other users will have opened emails before the scraper gets to them.
Can anyone see what the issue is?
import pandas as pd
from imap_tools import MailBox, AND
import re, time, datetime, os
from config import email, password
uids = []
yahooSmtpServer = "imap.mail.yahoo.com"
data = {
'today': str(datetime.datetime.today()).split(' ')[0],
'uids': []
}
while True:
while True:
try:
client = MailBox(yahooSmtpServer).login(email, password, 'INBOX')
try:
if not data['today'] == str(datetime.datetime.today()).split(' ')[0]:
data['today'] = str(datetime.datetime.today()).split(' ')[0]
data['uids'] = []
ds = str(datetime.datetime.today()).split(' ')[0].split('-')
msgs = client.fetch(AND(date_gte=datetime.date.today()))
for msg in msgs:
links = []
if str(datetime.datetime.today()).split(' ')[0] == str(msg.date).split(' ')[0] and not msg.uid in data['uids']:
mail = msg.html
if 'order' in mail and not 'cancel' in mail:
for i in re.findall(r'(https?://[^\s]+)', mail):
if 'pick' in i:
link = i.replace('"', "")
link = link.replace('<', '>').split('>')[0]
print(link)
links.append(link)
break
data['uids'].append(msg.uid)
scr_links = pd.DataFrame({'Links': links})
scr_links.to_csv('Links.csv', mode='a', header=False, index=False)
time.sleep(0.5)
except Exception as e:
print(e)
pass
client.logout()
time.sleep(5)
except Exception as e:
print(e)
print('sleeping for 5 sec')
time.sleep(1)
I think this is email server throttle timeout.
Try to see IMAP IDLE.
since 0.51.0 imap_tools has IDLE support:
https://github.com/ikvk/imap_tools/releases/tag/v0.51.0
I have the below code, which downloads a Gmail email and its attachments. It returns its attachments.
def gmailAPIDownloadAttachments(self, messageID, userID="me"):
try:
service = self.gmailAPIService
self.GLogger.info("Attempting to download attachments from messageID (" +str(messageID)+ ")")
message = self.gmailAPIGetFullMessage(messageID, userID=userID)
if message is False:
self.GLogger.error("Failed to extract message (" +str(messageID)+ ") for downloading attachments")
return False
attachmentList = list()
payload = message['payload']
if 'parts' in payload:
parts = payload['parts']
for part in parts:
if part['filename']:
if 'data' in part['body']:
data = part['body']['data']
else:
att_id = part['body']['attachmentId']
att = service.users().messages().attachments().get(userId=userID, messageId=messageID, id=att_id).execute()
data = att['data']
file_data = base64.urlsafe_b64decode(data.encode('UTF-8'))
filename = part['filename']
extSearch = filename.find('.')
if extSearch == -1:
ext = ""
partFileName = filename[0:extSearch]
else:
ext = filename[extSearch+1:]
partFileName = filename[0:extSearch]
theAttachment = Attachment(filename,partFileName, ext, file_data)
attachmentList.append(theAttachment)
self.GLogger.info("Successfully downloaded attachments from messageID (" +str(messageID)+ ")")
return(attachmentList)
except:
self.GLogger.error("Encountered an error while attempting to download email attacments from messageID (" +str(messageID)+ ")")
tb = traceback.format_exc()
self.GLogger.exception(tb)
return False
I understand how to convert fetching messages into batching. For example, this is how one could batch-fetch messages:
from apiclient.http import BatchHttpRequest
import json
batch = BatchHttpRequest()
#assume we got messages from Gmail query API
for message in messages:
batch.add(service.users().messages().get(userId='me', id=message['id'],
format='raw'))
batch.execute()
for request_id in batch._order:
resp, content = batch._responses[request_id]
message = json.loads(content)
#handle your message here, like a regular email object
However, the attachments aspect seem to have logic and other possible fetches such as in this part:
att_id = part['body']['attachmentId']
att = service.users().messages().attachments().get(userId=userID, messageId=messageID, id=att_id).execute()
data = att['data']
How can I effectively batch both fetching the message and its attachments? I would like to be able to quickly fetch many emails at once.
I'm writing a script to access a website using proxies with multiple threads but now I'm stuck in multiple threads, when I run the script below, it opens 5 browsers but all 5 use 1 proxy, I want 5 browsers to use different proxies, can someone help me complete it? thank you
Here is my script :
from selenium import webdriver
from selenium import webdriver
import time , random
import threading
def e():
a = open("sock2.txt", "r")
for line in a.readlines():
b = line
prox = b.split(":")
IP = prox[0]
PORT = int(prox[1].strip("\n"))
print(IP)
print(PORT)
profile = webdriver.FirefoxProfile()
profile.set_preference("network.proxy.type", 1)
profile.set_preference("network.proxy.socks", IP)
profile.set_preference("network.proxy.socks_port", PORT)
try:
driver = webdriver.Firefox(firefox_profile=profile)
driver.get("http://www.whatsmyip.org/")
except:
print("Proxy Connection Error")
driver.quit()
else:
time.sleep(random.randint(40, 70))
driver.quit()
for i in range(5):
t = threading.Thread(target=e)
t.start()
(Wish everyone has a happy and lucky new year)
Dominik Lašo captured it correctly - each threads processes the file from the beginning. Here's probably how it should look like:
from selenium import webdriver
from selenium import webdriver
import time , random
import threading
def e(ip, port):
profile = webdriver.FirefoxProfile()
profile.set_preference("network.proxy.type", 1)
profile.set_preference("network.proxy.socks", IP)
profile.set_preference("network.proxy.socks_port", PORT)
try:
driver = webdriver.Firefox(firefox_profile=profile)
driver.get("http://www.whatsmyip.org/")
except:
print("Proxy Connection Error")
driver.quit()
else:
time.sleep(random.randint(40, 70))
driver.quit()
my_threads = []
with open("sock2.txt", "r") as fd:
for line in fd.readlines():
line = line.strip()
if not line:
continue
prox = line.split(":")
ip = prox[0]
port = int(prox[1])
print('-> {}:{}'.format(ip, port))
t = threading.Thread(target=e, args=(ip, port,))
t.start()
my_threads.append(t)
for t in my_threads:
t.join()
( I personaly think that a problem is there that when you start a program, it will go to new thread, which will go throught the textfile from beginning, becasue you aint deleting them )
I have cane across the same problem, when I was doing the same thing as you do now. I know you would rather want help with your code, but I am in hurry to test it and want to help you ;) , so here is a code that works for me ... There is even task killer for a chrome ( you just have to edit it to firefox )
If I were you, I would start the thread after opening the file, cuz it looks liek you are opening the same file from 1st line everytime the tread starts
links = [ // Link you want to go to ]
def funk(xxx , website):
link = website
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--proxy-server=%s' % str(xxx))
chromedriver = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'chromedriver')
chrome = webdriver.Chrome(chromedriver, chrome_options=chrome_options)
try :
// Do stuff
except:
print('exception')
chrome.close()
for link in links:
f = open('proxies.txt')
line = f.readline()
x = 1
xx = 0
while line:
if number_of_used_proxies < 10:
print(line)
line = f.readline()
try:
threading.Timer(40, funk, [line, link]).start()
except Exception as e:
print(e)
time.sleep(1)
x += 1
number_of_used_proxies += 1
else:
time.sleep(100)
for x in range(1, 10):
try:
xzxzx = 'os.system("taskkill /f /im chrome.exe")'
os.system("killall 'Google Chrome'")
except:
print("NoMore")
time.sleep(10)
number_of_used_proxies = 0
f.close()
Hope it helps :)
vantuong: Here's how you can solve the problem with ThreadPoolExecutor.
Reference: https://docs.python.org/3/library/concurrent.futures.html
from selenium import webdriver
import time, random
#import threading
import concurrent.futures
MAX_WORKERS = 5
def get_proxys(data_file):
proxys = []
with open(data_file, "r") as fd:
for line in fd.readlines():
line = line.strip()
if not line:
continue
prox = line.split(":")
ip = prox[0]
port = int(prox[1])
proxys.append((ip, port))
return proxys
def e(ip, port):
profile = webdriver.FirefoxProfile()
profile.set_preference("network.proxy.type", 1)
profile.set_preference("network.proxy.socks", IP)
profile.set_preference("network.proxy.socks_port", PORT)
try:
driver = webdriver.Firefox(firefox_profile=profile)
driver.get("http://www.whatsmyip.org/")
except:
print("Proxy Connection Error")
driver.quit()
else:
time.sleep(random.randint(40, 70))
driver.quit()
with concurrent.futures.ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
proxys = get_proxys('sock2.txt')
tasks = {executor.submit(e, proxy[0], proxy[1]): proxy for proxy in proxys}
for task in concurrent.futures.as_completed(tasks):
proxy = tasks[task]
try:
data = task.result()
except Exception as exc:
print('{} generated an exception: {}'.format(proxy, exc))
else:
print('{} completed successfully'.format(proxy))
Fun exercise: Try playing around with different values of MAX_WORKERS.