3

I'm testing some web scraping on Instagram with Selenium and Python.

In this case I want to upload a picture.

Normally you have to click on the upload icon and choose the file from a window. How can I manage it with Selenium?

I tried:

driver.find_element_by_class_name("coreSpriteFeedCreation").send_keys('C:\\path-to-file\\file.jpg')

and also with find_element_by_xpath but I get an exception:

selenium.common.exceptions.WebDriverException: Message: unknown error: cannot focus element

I tried also only with click() but nothing happens.

Any Idea?

EDIT
Thanks to @homersimpson comment I tried this:

actions = ActionChains(driver)
element = driver.find_element_by_class_name("coreSpriteFeedCreation")
actions.move_to_element(element)
actions.click()
actions.send_keys('C:\\path-to-file\\file.jpg')
actions.perform()

Now the window to choose the file appears. The problem is that I would like to avoid this window and give directly the path of my file.

Danny_DD
  • 756
  • 1
  • 12
  • 34

3 Answers3

5

If right understand, you are trying to avoid handling with a native window. You can try this:

# get all inputs
inputs = driver.find_elements_by_xpath("//input[@accept = 'image/jpeg']").send_keys(os.getcwd() + "/image.png")

Now you can try all of them. I don't know which of them will work.

More about os.getcwd() is here

To be able to perform this code you have to have an element like this:

<input type="file" name="fileToUpload" id="fileToUpload2" class="fileToUpload">

EDIT:

It looks like instagram turned of input fields interaction for posts. For Account image it still works, but not for posting. I assume it is was done to prevent bots to post images. Anyway, there is a solution for this problem. You can use AutoIt like this:

import autoit
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
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.common.keys import Keys

ActionChains(driver).move_to_element( driver.find_element_by_xpath("//path/to/upload/button")).click().perform()
handle = "[CLASS:#32770; TITLE:Open]"
autoit.win_wait(handle, 60)
autoit.control_set_text(handle, "Edit1", "\\file\\path")
autoit.control_click(handle, "Button1")
Andrei Suvorkov
  • 5,559
  • 5
  • 22
  • 48
  • I get always `selenium.common.exceptions.WebDriverException: Message: unknown error: cannot focus element` – Danny_DD Jun 18 '18 at 15:08
  • 1
    Happy to hear it, today I have reached limit of down/upvotes, so tomorrow I'll upvote your question. You have a good one ) – Andrei Suvorkov Jun 18 '18 at 15:20
  • 1
    @AndreiSuvorkov : I'll do it for you. – cruisepandey Jun 18 '18 at 15:23
  • Little problem, it works perfectly but it opens the wrong input. With your code I can change my profile picture. I tried all the input in the DOM without success. Any ideas? – Danny_DD Jun 18 '18 at 15:31
  • Could you please provide a link where can I upload a picture as a post? I'm not an instagram user and can't find where to upload it – Andrei Suvorkov Jun 18 '18 at 16:41
  • 1
    I have changed my `xPath`. So I have found three elements according new `xPath`. I don't know which of them is the right one, but one of them should do the trick. Please try and tell me if it works, and which element was the right one. – Andrei Suvorkov Jun 18 '18 at 16:52
  • How can I try all of them? `send_keys` does not work with a list of web elements. – Danny_DD Jun 19 '18 at 07:58
  • I found actually 5 of them. But only one works and is the one for the profile pictures. I tried to show them on the page and click on it manually to check wich was the purpose of each form, and the result is the same: only one goes to the page to modify the profile pictures. With the other 4 you can choose a file and that's it, it just do nothing except showing the file name next to the button `choose file`. Quite challenging, because the chance to upload that file must be somewhere! – Danny_DD Jun 19 '18 at 09:29
  • I was trying to upload a photo/video on ig but I need it to work on ramote debian server and autoit works with windows only + only gui, need help. – Andrey Oct 28 '20 at 19:59
1

I think I may have found a solution that works for me. I found if you first have the bot click the plus icon while the browser is in the mobile view.

self.driver.find_element_by_xpath("/html/body/div[1]/section/nav[2]/div/div/div[2]/div/div/div[3]")\
        .click()

after that, I would immediately send my file to an input tag in the HTML and I find you may need to play around as to which one works but I find the last input tag worked for me.

self.driver.find_element_by_xpath("/html/body/div[1]/section/nav[2]/div/div/form/input")\
        .send_keys("/image/path.jpg")

The one weird thing about this is you will have a popup menu on top of the page but your code will still function with this window displayed over the window you are working on.

HumbleFox
  • 11
  • 2
1

Addition to HumbleFox's answer. To solve his problem regarding the pop-up box not closing or the file pop-up box not closing (bug)

The solution to this is to make the browser headless here's a part of my code for example:

mobile_emulation = { "deviceName": "Pixel 2" }
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--headless')
chrome_options.add_experimental_option("mobileEmulation", mobile_emulation)
chrome_options.binary_location = self.opt.binary_location
self.driver = webdriver.Chrome(executable_path=self.path, options=chrome_options)
xsephtion
  • 193
  • 1
  • 13