Selenium not clicking on LIKE button on Instagram - selenium

For some reason, the Instagram bot seems to work but selenium is not clicking on the Like button. What may be the issue? Thank you.
unique_photos = len(pic_hrefs)
for pic_href in pic_hrefs:
driver.get(pic_href)
time.sleep(2)
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
try:
time.sleep(random.randint(2, 4))
like_button = lambda: driver.find_element_by_xpath('//span[#aria-label="Like"]').click()
like_button().click()
print('Liked!')
for second in reversed(range(0, random.randint(18, 28))):
print_same_line("#" + hashtag + ': unique photos left: ' + str(unique_photos)
+ " | Sleeping " + str(second))
time.sleep(1)
except Exception as e:
time.sleep(2)
unique_photos -= 1

try this :
//article[1]//div[2]//section[1]//span[1]//button[1]//*[local-name()='svg']
and if you want to click on all like button then you need to use below xpath undoubtedly you need list to handle it ::
//article[*]//div[2]//section[1]//span[1]//button[1]//*[local-name()='svg']

Related

Selenium close alert in whatsapp bot

There is a bot that sends a message to numbers from a text file, but after switching to another person, there is an alert that needs to be confirmed.
However, it occurs when you open the next chat, and the alert processing goes the next line, but the code does not move further because it is waiting for the page to open. And I don't understand how to process these two cases at the same time
code:
def acceptAlert(driver):
try:
wait3 = WebDriverWait(driver, 10)
Alert = wait3.until(expected_conditions.alert_is_present())
if Alert is not None:
driver.switchTo().alert().dismiss()
except:
driver.get('https://web.whatsapp.com/send?phone=7' +
str(e[1:]) + '&test=sdfsdf')
time.sleep(5)
driver = webdriver.Chrome('C:\\Users\Marsel\AppData\Local\Programs\Python\Python38-32\chromedriver.exe')
test = open('base.txt', 'r')
lines = test.readlines()
i = 0
driver.get('https://web.whatsapp.com/send?phone=' + str(lines[i]) + '&test=sdfsdf')
time.sleep(15)
s = lines[i]
s = re.sub(r"[()'+']", "", s)
e = s.replace('-', '')
driver.get('https://web.whatsapp.com/send?phone=7' +
str(e[1:]) + '&test=sdfsdf')
time.sleep(5)
while i < len(lines):
driver.find_element_by_xpath('/html/body/div[1]/div/div/div[4]/div/footer/div[1]/div[2]/div/div[2]').send_keys('привет')
time.sleep(1)
driver.find_element_by_xpath(
'/html/body/div[1]/div/div/div[4]/div/footer/div[1]/div[2]/div/div[2]').send_keys(Keys.RETURN)
s = lines[i]
s = re.sub(r"[()'+']", "", s)
i += 1
acceptAlert(driver)
You should split them into separate functions and add try catch blocks.
def acceptAlert(driver):
try:
wait3 = WebDriverWait(driver, 10)
Alert = wait3.until(expected_conditions.alert_is_present())
if Alert is not None:
driver.switchTo().alert().accept()
except:
print('No alert found')
And then call this method inside your code loop. So when there is no alert, it will wait for 10 seconds and still continue execution even if there is no alert.

Selenium Bot: Irregular Switching of Windows

Once I'm clicking the element More Information, the link is getting clicked and then the window is jumping back to it's previous window and a TimeoutException is being shown.
Code:
self.driver.window_handles
base = "https://outlook.office.com/mail/inbox/id/AAQkADQ0ZmY1YmRkLWExNDEtNGNlYS1iOTZmLTVmNzNjMzhkNjUyMgAQAJmE%2FyrhD0supMphUUSGrmQ%3D"
window_set = {self.driver.window_handles[0], self.driver.window_handles[1]}
for x in window_set:
if(base != x):
self.driver.maximize_window()
wait = WebDriverWait(self.driver, 10)
self.driver.switch_to.window(x)
frame = wait.until(EC.presence_of_element_located((By.NAME, "mainFrame")))
self.driver.switch_to.frame(frame)
element = wait.until(EC.element_to_be_clickable((By.ID, "mc-lnk-moreInfo")))
element.click()
Please HELP!
WebPage Image:(contains both the tabs)
In this image More Information has been clicked and has changed to Less Information
This did the job!
self.driver.window_handles
wait = WebDriverWait(self.driver, 10)
base = self.driver.window_handles[0]
child = self.driver.window_handles[1]
windows = {self.driver.window_handles[0], self.driver.window_handles[1]}
for x in windows:
if(base != x):
self.driver.switch_to.window(x)
frame = wait.until(EC.presence_of_element_located((By.NAME, "mainFrame")))
self.driver.switch_to.frame(frame)
element = wait.until(EC.element_to_be_clickable((By.ID, "mc-lnk-moreInfo")))
element.click()

selenium with firefox close tab by javascript but SetTimeout() not ok

I use multithreaded way to open tab and when page finish load close tab
this is my open tab code
((JavascriptExecutor)webDriver).executeScript("window.open('"+url+"')");
When close tab,i iterate webDriver.getWindowHandles() and use function executeScript,but find some error,this is my code
this code work ok in chrome,it close all tab,but in firefox some windowHandler are closed and some not
((JavascriptExecutor) webDriver).executeScript("setTimeout(function(){window.close()},10000)");
or
((JavascriptExecutor) webDriver).executeScript("setInterval(function(){window.close()},10000)");
I try to use this code, but it's also like above code
((JavascriptExecutor) webDriver).executeScript("var script = document.createElement('script');\n" +
"script.type = 'text/javascript';\n" +
"script.innerHTML = 'setTimeout(function(){window.close()},10000);';\n" +
"script.innerHTML = 'window.close()';\n" +
"document.body.appendChild(script);");
but when i delete "script.innerHTML = 'setTimeout(function(){window.close()},10000);';\n" + only use window.close() it work close all tab, but does not meet the needs
so i think maybe setTimeout and setInterval function cause this problem in firefox
then i change code to this
((JavascriptExecutor) webDriver).executeScript("var start = null;\n" +
"\n" +
"function step(timestamp) {\n" +
" if (!start) start = timestamp;\n" +
" var progress = timestamp - start;\n" +
" if (progress < 2000) {\n" +
" window.requestAnimationFrame(step);\n" +
" } else {\n" +
" window.close();\n" +
" }\n" +
"}\n" +
"\n" +
"window.requestAnimationFrame(step);");
it's also some windowHandler are closed and some not
i don't know how can i close tab in firefox by javascript
The requirement is to close the tab directly after 10 seconds, or close the tab after the page is loaded
I'm not sure I fully understand the question but it seems you are trying to open a new tab, run some code, then close 10 seconds after it was opened?
I've tested this in firefox and it works with multiple tabs and each one closes on it's own.
((JavascriptExecutor) webDriver).executeScript(
"function openAndClose(url, timeout){" +
" var tab = window.open(url);" +
" setTimeout(function(){tab.close()},timeout);" +
"}" +
"openAndClose('https://www.google.com', 3000);");
If this is not it, could you explain your problem a little more clearly.

Scrapy can't figure out an sql query ins ajax call

I am trying to scrape data from this link https://www.flatstats.co.uk/racing-system-builder.php using scrapy.
I want to automate the ajax call using scrapy.
When I click "Full SP" Button (inspect in Firebug) the post parameter has the sql string which is "strange"
race|2|eq|Ordinary|0|~tRIDER_TYPE
What dialect is this?
My code :
import scrapy
import urllib
class FlatStat(scrapy.Spider):
name= "flatstat"
allowed_domains = ["flatstats.co.uk"]
start_urls = ["https://www.flatstats.co.uk/racing-system-builder.php"]
def parse(self, response):
query_lst = response.xpath('//table[#id="system"]//tr/td[last()]/text()').extract()
query_str = ' '.join(query_lst)
url = 'https://www.flatstats.co.uk/ajax/sb_report.php'
body_dict = {'a_e_max': '9.99',
'a_e_min': '0',
'arch_min': '0',
'exp_min': '0',
'report_type':'S',
# copied from the Post parameters by inspecting. Actually I tried everything.
'sqlFullString' : u'''Type%20(Rider)%7C%3D%7COrdinary%20(Exclude%20Amatr%2C%20App%2C%20Lady%20Races
)%7CAND%7Crace%7C2%7C0%7COrdinary%7C0%7C~tRIDER_TYPE%7C-t%7Ceq''',
#I tried copying this from the post parameters as well but no success.
#I also tried sql from the table //td text() which is "normal" sql but no success
'sqlString': query_str}
#here i tried everything FormRequest as well though there is no form.
return scrapy.Request(url, method="POST", body=urllib.urlencode(body_dict), callback=self.parse_page)
def parse_page(self, response):
with open("response.html", "w") as f:
f.write(response.body)
So questions are:
What is this sql.
Why isn't it returning me the required page. How can I run the right query?
I tried Selenium as well to click the button and let it do the stuff it self but that is another unsuccessful story. :(
It's not easy to say what the website creator is doing with the submitted sqlString. It probably means something very specific to how the data is processed by their backend.
This is an extract of the page JavaScript in-HTML code:
...
function system_report(type) {
sqlString = '', sqlFullString = '', rowcount = 0;
$('#system tr').each(function() {
if(rowcount > 0) {
var editdata = this.cells[6].innerHTML.split("|");
sqlString += editdata[0] + '|' + editdata[1] + '|' + editdata[7] + '|' + editdata[3] + '|' + editdata[4] + '|' + editdata[5] + '^';
sqlFullString += this.cells[0].innerHTML + '|' + encodeURIComponent(this.cells[1].innerHTML) + '|' + this.cells[2].innerHTML + '|' + this.cells[3].innerHTML + '|' + this.cells[6].innerHTML + '^';
}
rowcount++;
});
sqlString = sqlString.slice(0, -1)
...
Looks non trivial to reverse-engineer.
Although it's not a solution to your "sql" question above, I suggest that you try using splash (an alternative to selenium in some cases).
You can launch it with docker (the easiest way):
$ sudo docker run -p 5023:5023 -p 8050:8050 -p 8051:8051 scrapinghub/splash
With the following script:
function main(splash)
local url = splash.args.url
assert(splash:go(url))
assert(splash:wait(0.5))
-- this clicks the "Full SP" button
assert(splash:runjs("$('#b-full-report').click()"))
-- loading the report takes some time
assert(splash:wait(5))
return {
html = splash:html()
}
end
you can get the page HTML with the popup of the report.
You can integrate Splash with Scrapy using scrapyjs (a.k.a scrapy-splash)
See https://stackoverflow.com/a/35851072/ with an example how to do so with a custom script.

Is it possible to take a screenshot of the whole page with Selenium/Capybara?

PhantomJS has the option of taking a screenshot of the whole page (not just the current viewport). Is there any way to do so using Selenium? I am running the Cucumber/Capybara tests headlessly, using the headless gem. I would use PhantomJS, but I've had some other problems with it.
In case anyone washed up this shore looking for how to do this with Poltergeist you just need to pass the full argument:
page.save_screenshot('screen.png', full: true) # If providing a custom file name.
page.save_screenshot(full: true) # Capybara sets a name based on timestamp.
page.save_and_open_screenshot('screen.png', full: true) # Same as save_screenshot.
page.save_and_open_screenshot(full: true) # Same as save_screenshot.
Docs.
Hope it helps!
Turns out I've been using the take_screenshot method that was provided by the headless gem, when I could have just used the page.save_screenshot() method, which does exactly what I need. Thank you, Andrey.
I tried a lot of things to get full height working with Capybara/Selenium.
Only one thing I tried seemed to work, and it was using headless_chrome. Bear in mind that I use a loop to take screenshots at different widths:
def screenshot
driver = Capybara.current_session.driver
window = Capybara.current_session.driver.browser.manage.window
widths = [320, 1380] #leave normal w as last
widths.each do |w|
window.resize_to(w, 900)
total_width = driver.execute_script("return document.body.offsetWidth")
total_height = driver.execute_script("return document.body.scrollHeight")
window.resize_to(total_width, total_height)
save_screenshot
end
end
I resize it twice to get the height info.
rails_helper.rb:
Capybara.register_driver :headless_chrome do |app|
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
chromeOptions: {
"args" => %w{
headless
disable-gpu
--disable-notifications
}
}
)
Capybara::Selenium::Driver.new app,
browser: :chrome,
desired_capabilities: capabilities
end
Capybara.javascript_driver = :headless_chrome
Capybara.current_driver = :headless_chrome
You could also do something like this:
After do |scenario|
take_screenshot(#browser, scenario)
end
def take_screenshot(browser, scenario)
if scenario.failed?
scenario_name = scenario.name.gsub /[^\w\-]/, ' '
time = Time.now.strftime("%Y-%m-%d %H%M")
screenshot_path = './failed_png/' + time + ' - ' + scenario_name + '.png'
else
scenario_name = scenario.name.gsub /[^\w\-]/, ' '
time = Time.now.strftime("%Y-%m-%d %H%M")
screenshot_path = './success_png/' + time + ' - ' + scenario_name + '.png'
end
browser.save_screenshot(screenshot_path)
end
If you make a failed_png and success_png folder, this code will take a screenshot for each success and failure, and put it in the respective folders with the timestamp on it. This code goes in your env.rb file, and makes it so you do not have to use any helpers or add any extra code to your step defs.