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 name | Surname | Mail

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 McTrollfaceEmail: 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!