In [1]:
import requests
from bs4 import BeautifulSoup
from IPython.core.display import HTML

First, let's inspect the website we want to post to. This is a (nonfunctional) copy of our newsletter registration.

In [2]:
r = requests.get("https://www.physik.uzh.ch/~python/python/lecture_visual/test.html")

Since jupyter notebooks are rendered in the browser anyways, rendering a website is perfectly possible:

In [3]:
HTML(r.text)
Out[3]:
Test page

Newsletter

If you are interested to get an announcement about the exact date of the next editions, please sign up.
We send the announcement for a new school to everyone who registered within the two previous years. So once signed up, you should receive exactly two emails from us.
If you nevertheless want to unregister, please contact us via python@physik.uzh.ch.

First nameSurnameMail

In order find out where we need to post our content to, let's inspect the source code, as parsed by BeautifulSoup:

In [4]:
soup = BeautifulSoup(r.content, "lxml")
soup
Out[4]:
<html>
<head>
<title>Test page</title>
<style>
body {
    background-color: #e3e7ea;
</style>
</head>
<body>
<h2>Newsletter</h2>
<p>If you are interested to get an announcement about the exact date of the next editions, please sign 
up.
We send the announcement for a new school to everyone who registered within the two previous years. So once 
signed up, you should receive exactly two emails from us.
If you nevertheless want to unregister, please contact us via <a class="internal" href="mailto:python@physik.uzh.ch">python@physik.uzh.ch</a>.</p>
<form action="test.php" id="" method="post" name="form1">
<p></p><table class="register" style="table-layout:fixed; font-size:100%" width="">
<col width="260"/><col width="260"/><col width="260"/>
<tr>
<td><b> First name</b></td><td><b>Surname</b></td><td><b>Mail</b></td>
</tr>
<tr>
<td><input id="" name="firstname" type="text" value=""/></td>
<td><input id="" name="surname" type="text" value=""/></td>
<td><input id="" name="mail" type="text" value=""/></td>
</tr>
</table>
<input id="" name="button" size="30" type="submit" value="Submit"/>
<input id="" name="button" size="30" type="reset" value="Reset"/>
</form>
</body>
</html>

You can use CSS selectors

In [5]:
soup.select("input")
Out[5]:
[<input id="" name="firstname" type="text" value=""/>,
 <input id="" name="surname" type="text" value=""/>,
 <input id="" name="mail" type="text" value=""/>,
 <input id="" name="button" size="30" type="submit" value="Submit"/>,
 <input id="" name="button" size="30" type="reset" value="Reset"/>]

Or normal methods like find_all:

In [6]:
soup.find_all("input", attrs={"type": "text"})
Out[6]:
[<input id="" name="firstname" type="text" value=""/>,
 <input id="" name="surname" type="text" value=""/>,
 <input id="" name="mail" type="text" value=""/>]

But all we really need is the fact that the form gets posted to test.php with three input fields called firstname, surname and mail. This we can pass as a dictionary in a call to requests.post as the data keyword argument:

In [7]:
r2 = requests.post("https://www.physik.uzh.ch/~python/python/lecture_visual/test.php",
                   data={"firstname": "Troll",
                         "surname": "McTrollface",
                         "mail": "spam@example.com"})

The result we get back is that we have successfully registered to the newsletter:

In [8]:
HTML(r2.text)
Out[8]:
Test newsletter registration

Name: Troll McTrollface
Email: spam@example.com

You have been registered for the news letter!
Please be aware that this does not replace the registration!


If you have further questions or remarks please contact us python@physik.uzh.ch!