Login, Navigate and Retrieve data behind a proxy with Python

2024/11/18 22:53:12

I want, with a python script, to be able to login a website and retrieve some data. This behind my company's proxy.

I know that this question seems a duplicate of others that you can find searching, but it isn't.

I already tried using the proposed solutions in the responses to those answers but they didn't work... I don't only need a piece of code to login and get a specific webpage but also some "concepts" behind how all this mechanism works.

Here is a description of what I want to be able to do:

Log into a website > Get to page X > Insert data in some form of page X and push "Calculate" button > Capture the results of my query

Once I have the results I'll see how to sort how the data.

How can I achieve this behind a proxy? Every time I try to use "request" library to login it doesn't work saying I am unable to get page X since I did not authenticate... or worst, I am even unable to get to that side because I didn't set up the proxy before.

Answer

Clarification of Requirements

First, make sure you understand context for getting results of your calculation

(F12 shall show DevTools in Chrome or Firebug in Firefox where you can learn most details discussed below)

  • do you manage accessing from the target page your web browser?
  • is it really necessary to use proxy? If yes, then test it in the browser and note exactly what proxy to use
  • what sort of authentication you have to use to access target web app. Options being "basic", "digest", or some custom, requiring filling in some form and having something in cookies etc.
  • when you access the calculation form in your browser, does pressing "Calculate" button result in visible HTTP request? Is it POST? What is content of the request?

Simple: HTTP based scenario

It is very likely, that your situation will allow use of simple HTTP communication. I will assume following situation:

  • proxy is used and you know the url and possibly user name and password to use the proxy
  • All pages on target web application require either basic authentication or digest one.
  • Calculation button is using classical HTML form and results in HTTP POST request with all data see in form parameters.

Complex: Browser emulation scenario

There are some chances, that part of interaction needed to get your result is dependent on JavaScript code performing something on the page. Often it can be converted into HTTP scenario by investigating, what are final HTTP requests, but here I will assume this is not feasible or possible and we will emulate using real browser.

For this scenario I will assume:

  • you are able to perform the task yourself in web browser and have all required information available
    • proxy url
    • proxy user name and password, if required
    • url to log in
    • user name and password to fill into some login form to get in
    • knowing "where to follow" after login to reach your calculation form
  • you are able to find enough information about each page element to use (form to fill, button to press etc.) like name of it, id, or something else, which will allow to target it at the moment of simulation.

Resolving HTTP based scenario

Python provides excellent requests package, which shall serve our needs:

Proxy

Aassuming proxy at http://10.10.1.10:3128, username being user and password pass

import requests
proxies = {"http": "http://user:[email protected]:3128/",
}
#ready for `req = requests.get(url, proxies=proxies)`

Basic Authentication

Assuming, the web app allows access for user being appuser and password apppass

url = "http://example.com/form"
auth=("appuser", "apppass")
req = requests.get(url, auth=auth)

or using explicitly BasicAuthentication

from requests.auth import HTTPBasicAuth
url = "http://example.com/path"
auth = HTTPBasicAuth("appuser", "apppass")
req = requests.get(url, auth=auth)

Digest authentication differs only in classname being HTTPDigestAuth

Other authentication methods are documented at requests pages.

HTTP POST for a HTML Form

import requests
a = 4
b = 5
data = {"a": a, "b": b}
url = "http://example.com/formaction/url"
req = requests.post(url, data=data)

Note, that this url is not url of the form, but of the "action" taken, when you press the submit button.

All together

Users often go to the final HTML form in two steps, first log in, then navigate to the form.

However, web applications typically allow (with knowledge of the form url) direct access. This will perform authentication at the same step and this is the way described below.

Note: If this would not work, you would have to use sessions with requests, which is possible, but I will not elaborate on that here.

import request
from requests.auth import HTTPBasicAuth
proxies = {"http": "http://user:[email protected]:3128/",
}
auth = HTTPBasicAuth("appuser", "apppass")
a = 4
b = 5
data = {"a": a, "b": b}
url = "http://example.com/formaction/url"
req = requests.post(url, data=data, proxies=proxies, auth=auth)

By now, you shall have your result available via req and you are done.

Resolving Browser emulation scenario

Proxy

Selenimum doc for configuring proxy recommends configuring your proxy in your web browser. The same link provides details, how to set up proxy from your script, but here I will assume, you used Firefox and have already (during manual testing) succeeded with configuring proxy.

Basic or Digest Authentication

Following modified snippet originates from SO answer by Mimi, using Basic Authentication:

from selenium import webdriverprofile = webdriver.FirefoxProfile()
profile.set_preference('network.http.phishy-userpass-length', 255)
driver = webdriver.Firefox(firefox_profile=profile)
driver.get("https://appuser:[email protected]/")

Note, that Selenium does not seem providing complete solution for Basic/Digest authentication, the sample above is likely to work, but if not, you may check this Selenium Developer Activity Google Group thread and see, you are not alone. Some solutions might work for you.

Situation with Digest Authentication seems even worse then with Basic one, some people reporting success with AutoIT or blindly sending keys, discussion referenced above shows some attempts.

Authentication via Login Form

If the web site allows logging in by entering credentials into some form, you might be lucky one, as this is rather easy task to do with Selenium. For more see next chapter about Filling in forms.

Fill in a Form and Submit

In contrast to Authentication, filling data into forms, clicking buttons and similar activities are where Selenium works very well.

from selenium import webdrivera = 4
b = 5
url = "http://example.com/form"
# formactionurl = "http://example.com/formaction/url" # this is not relevant in Selenium# Start up Firefox
browser = webdriver.Firefox()# Assume, you get somehow authenticated now
# You might succeed with Basic Authentication by using url = "http://appuser:[email protected]/form# Navigate to your url
browser.get(url)# find the element that's id is param_a and fill it in
inputElement = browser.find_element_by_id("param_a")
inputElement.send_keys(str(a))
# repeat for "b"
inputElement = browser.find_element_by_id("param_b")
inputElement.send_keys(str(b))# submit the form (if having problems, try to set inputElement to the Submit button)
inputElement.submit()time.sleep(10) # wait 10 seconds (better methods can be used)page_text = browser.page_source
# now you have what you asked for
browser.quit()

Conclusions

Information provided in question describes what is to be done in rather general manner, but is lacking specific details, which would allow providing tailored solution. That is why this answer focuses on proposing general approach.

There are two scenarios, one bing HTTP based, second one uses emulated browser.

HTTP Solution is preferable, despite of a fact, it requires a bit more preparation in searching, what HTTP requests are to be used. Big advantage is, it is then in production much faster, requiring much less memory and shall be more robust.

In rare cases, when there is some essential JavaScript activity in the browser, we may use Browser emulation solution. However, this is much more complex to set up and has major problems at the Authentication step.

https://en.xdnf.cn/q/120019.html

Related Q&A

overflow in exp, python

cant really figure out why this error RuntimeWarning: overflow encountered in exp is showing up. The function Im trying to implement is:Id = lambda t_u, yp: Is * (np.exp((Vin(t_u) - L*yp)/(n_Ut*Ut)) - …

Getting a matlab codes results on python

I have code in matlab whose results I would like to use in python code (as a matrix or as a .dat file). Could anyone tell me how this could be done?

My Status object is not saving in Django

When I enter the shell, I run into the following problem:from users.models import Status from django.utils import timezoneStatus.objects.all() >>> [] p = Status() p.status_time = timezone.date…

Too many instances are running for Django Server

When Django server gets started, I can see only one instance of Django server running in the background. But after a while, I can see multiple instances are running.Output:root@GoldenGate:~# ps |grep p…

Not able to display images from static folder using Django

This is my home.html Im not able to display the images in static/images/ folder. Although *[09/Mar/2020 15:52:09] "GET /static/images/mona.jpg HTTP/1.1" 404 1669 * is displayed in terminal.&l…

Regex to match phone number 5ABCDYYZZ [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.Want to improve this question? Add details and clarify the problem by editing this post.Closed 1 year ago.Improve …

Remove an \\n\\t\\t\\t-element from list

I got the following list called "phonenumbers". I struggle to remove the elements which contain \n\t\t\t and \n\t\t\t\t. I tried "try and except"-methode and remove(\n\t\t\t\t) but …

Find all numbers in a string in Python 3 [duplicate]

This question already has answers here:How to extract numbers from a string in Python?(20 answers)Split Strings into words with multiple word boundary delimiters(31 answers)Closed 8 years ago.Newbie h…

call dictionary from one function to another

How can I call a dictionary created in one function to another?I have tried using How do I access a dictionary from a function to be used in another function? but it doesnt work for me.I have created…

How to change values in numpy array

import numpy as np a=np.array([[4,2,6],[3,6,5]]) b=np.array([3,5])I want to update the numbers in "a" which are bigger than the numbers in "b" to np.nan. If they are smaller or equa…