{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "d9beab72",
   "metadata": {},
   "source": [
    "# In-Class Exercises, Session 3"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bcba624a",
   "metadata": {},
   "source": [
    "<U>Notes if you are using Jupyter Notebook</U>:  to call <B>exit()</B> from a notebook, please use <B>sys.exit()</B> (requires <B>import sys</B>).\n",
    "\n",
    "If a strange error occurs, it may be because Jupyter retains variables from all executed cells.  To reset the notebook, click 'Restart Kernel' (the circular arrow) -- this will reset variables, but will not undo any changes made."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3f458a5d",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4c287bba",
   "metadata": {},
   "source": [
    "REQUESTS:  VIEWING RESPONSE"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "699247da",
   "metadata": {},
   "source": [
    "<B>3.1:  <U>Issue a GET request, view response text with .text</U>.  Use <B>requests.get()</B> with a url to retrieve a response from the weather service.  Print the <B>.text</B> attribute to see the body of the response.  </B>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0c114698",
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests\n",
    "\n",
    "url = 'https://forecast.weather.gov/product.php?site=NWS&issuedby=CTP&product=AFD'\n",
    "\n",
    "response = requests.get()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "80c7eb30",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a68bdaba",
   "metadata": {},
   "source": [
    "<B>3.2:  <U>Issue a GET request, view headers</U>.  Print the <B>.headers</B> attribute of the response to see the headers sent back by the weather server.  </B>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "80390c07",
   "metadata": {},
   "source": [
    "You can also loop through the dict-like <B>response.headers</B> to see each key/value pair clearly."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c5dad81f",
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests\n",
    "\n",
    "url = 'https://forecast.weather.gov/product.php?site=NWS&issuedby=CTP&product=AFD'\n",
    "\n",
    "response = requests.get(url)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3817abae",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c7e464d0",
   "metadata": {},
   "source": [
    "<B>3.3:  <U>Issue a GET request, view status code</U>.  Print the <B>.status\\_code</B> attribute from the response, </B>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "32b2f996",
   "metadata": {},
   "source": [
    "Next, change one of the parameters to see how the code changes; also, change the spelling of the word 'product'.\n",
    "\n",
    "In addition, use <B>requests.status\\_codes.\\_codes[response.status\\_code]</B> with the status code to see the meaning of the response code.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "28442883",
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests\n",
    "\n",
    "url = 'https://forecast.weather.gov/product.php?site=NWS&issuedby=CTP&product=AFD'\n",
    "\n",
    "response = requests.get(url)\n",
    "\n",
    "\n",
    "# print(requestH.status_codes._codes[])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "17d86688",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "861b8315",
   "metadata": {},
   "source": [
    "REQUESTS:  ENCODED (text) and UNENCODED (bytes) RESPONSE"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c6bf8f12",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "585d53d7",
   "metadata": {},
   "source": [
    "<B>3.4:  <U>Issue a web request, view response.text (decoded) and response.content (undecoded)</U>.</B>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e1aff407",
   "metadata": {},
   "source": [
    "With the first URL, check the type of <B>response.text</B> and the type of <B>response.content</B>.  Each contains the response content, but one is <I>decoded</I> as a string and the other is <I>encoded</I> as bytes.\n",
    "\n",
    "Next, check the value of <B>response.encoding</B> to see what encoding the yahoo page uses.  The check the same with the Microsoft English page and the Microsoft French page."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8398b563",
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests\n",
    "\n",
    "url = 'http://www.yahoo.com'\n",
    "\n",
    "# url = 'https://www.microsoft.com/en-us/'      # Microsoft in English\n",
    "# url = 'https://www.microsoft.com/fr-fr/'      # Microsoft in French\n",
    "\n",
    "response = requests.get(url)\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bd4f4341",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a3764a8e",
   "metadata": {},
   "source": [
    "<B>3.5:  <U>Saving an image, sound or zip file</U>.  Issue the below web request, open a local file with 'wb' (meaning, \"write as bytes\") and write the unencoded text to the file.  (To access unencoded text, use <B>response.content</B> instead of <B>reponse.text</B>)</U>.</B>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "01a176a1",
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests\n",
    "\n",
    "url = 'https://davidbpython.com/advanced_python/supplementary/python.png'   # a URL to an image\n",
    "\n",
    "response = requests.get(url)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e43ca7f7",
   "metadata": {},
   "source": [
    "Check the folder where this script or notebook is located; you should find the image file there."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fa4440bc",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a829ed92",
   "metadata": {},
   "source": [
    "LAB"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "33543aa1",
   "metadata": {},
   "source": [
    "<div style=\"background-color: #ccffcc; padding: 10px; border: 2px solid green\"><B>3.6:  <U>Retrieve a page and save to disk</U>.  </B></div>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8d5ccd5d",
   "metadata": {},
   "source": [
    "Download the following page and save to disk in a new file (write <B>response.text</B> to the file).  Make sure to close the file.\n",
    "\n",
    "After writing the file, please open the file in a browser (use your browser's <B>File > Open File</B> menu command).\n",
    "\n",
    "In another tab on your browser, open the url directly.  Compate the two pages.\n",
    "\n",
    "(The locally saved file will not have correct formatting or colors - this is because these are supplied by a separate CSS file that was not downloaded.)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9a1f4db3",
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests\n",
    "\n",
    "url = 'https://pycoders.com/'\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c98a1030",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "583b36cf",
   "metadata": {},
   "source": [
    "<div style=\"background-color: #ccffcc; padding: 10px; border: 2px solid green\"><B>3.7:  <U>View response status code</U>.  </B></div>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e888cd6b",
   "metadata": {},
   "source": [
    "Continuing the previous exercise, use the <B>.status\\_code</B> attribute to view the response status.  Now change the URL to something you wouldn't expect to be correct, run and view the status code."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "23892720",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7e86987d",
   "metadata": {},
   "source": [
    "<div style=\"background-color: #ccffcc; padding: 10px; border: 2px solid green\"><B>3.8:  <U>View response headers</U>.  </B></div>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "92826266",
   "metadata": {},
   "source": [
    "Continuing the previous exercise, use the <B>.headers</B> attribute to retrieve the headers coming back as a dict from the response.  Loop through and print each key/value pair in the dict."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6e27ba7f",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dc5f08c5",
   "metadata": {},
   "source": [
    "<div style=\"background-color: #ccffcc; padding: 10px; border: 2px solid green\"><B>3.9:  <U>Retrieve and save an image</U>.  </B></div>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e951409b",
   "metadata": {},
   "source": [
    "Use the below URL to retrieve an image from the internet, and save it locally to a filename of your choice (make sure it has a <B>.jpg</B> file extension so it is recognized properly by your image viewer).\n",
    "\n",
    "The data must be read and written as binary data (i.e., not plaintext).  Therefore when writing, use 'wb' (write binary) instead of 'w'.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e2902ccf",
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests\n",
    "\n",
    "url = 'https://cdn.vox-cdn.com/uploads/chorus_image/image/32167377/monty-python-3by2.0.jpg'\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "12bc875f",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "52f6d13e",
   "metadata": {},
   "source": [
    "REQUESTS:  CONFIGURING THE REQUEST"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bcd385f9",
   "metadata": {},
   "source": [
    "<B>3.10:  <U>Demo exercise:  issue a request and view elements of the request</U>.</B>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6a8eb851",
   "metadata": {},
   "source": [
    "First, issue the following request and view the headers reflected back.\n",
    "\n",
    "Next, uncomment the 'headers' lines to see how http\\_reflect \"sees\" you (i.e., what browser and platform it thinks you are requesting from).\n",
    "\n",
    "Finally, change 'text/plain' to 'text/html' and see http\\_reflect respond with HTML instead of plain text."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "714f2371",
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests\n",
    "\n",
    "spoof_browser = \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36\"\n",
    "\n",
    "response = requests.get('http://davidbpython.com/cgi-bin/http_reflect'\n",
    "                        #, headers={\n",
    "                        #         'User-Agent':  spoof_browser,\n",
    "                        #         'Accept':      'text/plain',\n",
    "                        #         }\n",
    "                        )\n",
    "\n",
    "print(response.text)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "131b269f",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "47dbd891",
   "metadata": {},
   "source": [
    "<B>3.11:  <U>Demo exercise:  issue a request and send parameters with .get()</U>.</B>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5081f22c",
   "metadata": {},
   "source": [
    "In the below program, add the <B>params=</B> argument with the dict 'my\\_params' to send key/value pairs to the <B>http\\_reflect</B> service as part of the query string.  In the response, find the parameters you sent.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d34fa50a",
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests\n",
    "\n",
    "my_params = {'a': 1, 'b': 'hello'}\n",
    "\n",
    "response = requests.get('http://davidbpython.com/cgi-bin/http_reflect')\n",
    "\n",
    "print(response.text)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4aca2bdc",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "034593a5",
   "metadata": {},
   "source": [
    "<B>3.12:  <U>Issue a request and send parameters with .post()</U>.</B>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fd31143b",
   "metadata": {},
   "source": [
    "In the below program, add the <B>data=</B> argument with the dict 'my\\_data' to send key/value pairs to the <B>http\\_reflect</B> service as part of the body of the request.  In the response, find the parameters you sent.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ab7082fa",
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests\n",
    "\n",
    "my_data = {'a': 1, 'b': 'hello'}\n",
    "\n",
    "response = requests.post('http://davidbpython.com/cgi-bin/http_reflect')\n",
    "\n",
    "print(response.text)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "514fba35",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b419247b",
   "metadata": {},
   "source": [
    "REQUESTS:  UPLOADING A FILE"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0b086cfc",
   "metadata": {},
   "source": [
    "<B>3.13:  <U>Upload a file to a server program</U>.  Add the <B>files=</B> parameter to <B>.post()</B> to upload the below file.</B>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "76825163",
   "metadata": {},
   "source": [
    "Note that the file has been opened with 'rb', which stands for 'read binary':  we are uploading encoded bytes."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ece4766f",
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests\n",
    "\n",
    "# open file for reading without decoding (returns a bytestring)\n",
    "file_bytes = open('../test_file.txt', 'rb')\n",
    "\n",
    "file_dict = { 'file':  ('test_file.txt', file_bytes,\n",
    "                        'text/plain') }\n",
    "\n",
    "response = requests.post('https://davidbpython.com/cgi-bin/http_reflect')\n",
    "\n",
    "print(response.text)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6e93263c",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "60d0e793",
   "metadata": {},
   "source": [
    "LAB"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "38f1220a",
   "metadata": {},
   "source": [
    "<div style=\"background-color: #ccffcc; padding: 10px; border: 2px solid green\"><B>3.14:  <U>Demo exercise:  issue request with headers, parameters and data</U>.</B></div>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4a85a991",
   "metadata": {},
   "source": [
    "Please note below the approach for setting <B>headers</B>, <B>parameters</B> and <B>data</B> in a request, and note that each have been successfully sent to (and reflected back from) the server."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "41e9a379",
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests\n",
    "\n",
    "# link to my reflection program\n",
    "url = 'http://davidbpython.com/cgi-bin/http_reflect'\n",
    "\n",
    "div_bar = '=' * 10\n",
    "\n",
    "\n",
    "# headers, parameters and message data to be passed to request\n",
    "# change to 'text/html' for an HTML response\n",
    "header_dict =  { 'Accept': 'text/plain' }\n",
    "param_dict =   { 'key1': 'val1', 'key2': 'val2' }\n",
    "data_dict =    { 'text1': \"We're all out of gouda.\" }\n",
    "\n",
    "\n",
    "# a GET request (change to .post for a POST request)\n",
    "response = requests.get(url, headers=header_dict,\n",
    "                             params=param_dict,\n",
    "                             data = data_dict)\n",
    "\n",
    "\n",
    "# status of the response (OK, Not Found, etc.)\n",
    "response_status = response.status_code\n",
    "\n",
    "# headers sent by the server\n",
    "response_headers = response.headers\n",
    "\n",
    "# body sent by server\n",
    "response_text = response.text\n",
    "\n",
    "\n",
    "# outputting response elements (status, headers, body)\n",
    "\n",
    "# response status\n",
    "print(f'{div_bar} response status {div_bar}\\n')\n",
    "print(response_status)\n",
    "print(); print()\n",
    "\n",
    "# response headers\n",
    "print(f'{div_bar} response headers {div_bar}\\n')\n",
    "for key in response_headers:\n",
    "    print(f'{key}:  {response_headers[key]}\\n')\n",
    "print()\n",
    "\n",
    "# response body\n",
    "print(f'{div_bar} response body {div_bar}\\n')\n",
    "print(response_text)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f91405e0",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0b63cab5",
   "metadata": {},
   "source": [
    "<div style=\"background-color: #ccffcc; padding: 10px; border: 2px solid green\"><B>3.15:  <U>Use a parameter to configure a web API request</U>.  </B></div>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8454733a",
   "metadata": {},
   "source": [
    "Complete a request from the below URL by using the parameter <B>term</B> with a value that is a term you would like to search on <B>urbandictionary.com</B>.\n",
    "\n",
    "(<U>Warning</U>:  <B>urbandictionary.com</B> definitions can use offensive language.  For a \"clean\" set of definitions, try the defition for <B>squee</B> as shown below.)\n",
    "\n",
    "Read and save the resulting JSON text to a file."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "da6259e7",
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests\n",
    "\n",
    "url = 'http://api.urbandictionary.com/v0/define'\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "db814a8c",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7ddd2ddc",
   "metadata": {},
   "source": [
    "<div style=\"background-color: #ccffcc; padding: 10px; border: 2px solid green\"><B>3.16:  <U>Read and parse JSON data</U>.  </B></div>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cd98c5b0",
   "metadata": {},
   "source": [
    "Continue the previous program by using the <B>.json()</B> method of the <B>response</B> object to read the data as a JSON object.\n",
    "\n",
    "You should find that the object is a <B>dict</B>, that it has one key <B>list</B> with a value that is a list, and that if you loop through this list of dicts, the key <B>author</B> is the author's name, and <B>definition</B> is the definition."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "177aa3c0",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0587048f",
   "metadata": {},
   "source": [
    "<div style=\"background-color: #ccffcc; padding: 10px; border: 2px solid green\"><B>3.17:  <U>Read and parse CSV data</U>.  </B></div>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f327c034",
   "metadata": {},
   "source": [
    "Request the following data and retrieve as text.  Load the text as a <B>csv.reader</B> object, then read line-by-line and print out each parsed line.\n",
    "\n",
    "(Hint:  to load the data into text into <B>csv.reader</B>, split the text using <B>.splitlines()</B> first, and pass this list to <B>csv.reader()</B>.)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "533eecbe",
   "metadata": {},
   "outputs": [],
   "source": [
    "import csv\n",
    "import requests\n",
    "\n",
    "url = 'http://davidbpython.com/advanced_python/supplementary/dated_file.csv'\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "16abd692",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "541ac1d0",
   "metadata": {},
   "source": [
    "WEB SCRAPING"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "576ecc94",
   "metadata": {},
   "source": [
    "<B>3.18:  <U>BeautifulSoup object</U>:  the below code reads a string read from an html file and parses the file and its tags into a <B>BeautifulSoup</B> object.  </B>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "66ef7744",
   "metadata": {},
   "source": [
    "Explore the following attributes of the object named 'soup':\n",
    "<UL>\n",
    "  <LI> print the type of the object</LI>\n",
    "  <LI> print the object itself</LI>\n",
    "  <LI> print the <B>.text</B> attribute</LI>\n",
    "</UL>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2ea8752e",
   "metadata": {},
   "outputs": [],
   "source": [
    "from bs4 import BeautifulSoup\n",
    "\n",
    "scrapee = '../dormouse.html'\n",
    "\n",
    "text = open(scrapee).read()\n",
    "soup = BeautifulSoup(text, 'html.parser')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a2668ab4",
   "metadata": {},
   "source": [
    "Note that you may occasionally encounter a <B>UnicodeDecodeError</B> when you attempt to read a file from the internet.  In these cases you should tell Python which encoding to use:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c51cdd78",
   "metadata": {},
   "outputs": [],
   "source": [
    "text = open(scrapee, encoding='utf-8')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a78b89af",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7eec8130",
   "metadata": {},
   "source": [
    "<B>3.19:  <U>\"first tag\" attribute access; <B>.text</B> attribute</U>:  access the object for <B>soup.title</B>, <B>soup.body</B>, <B>soup.p</B>, <B>soup.meta</B>.  </B>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f590f112",
   "metadata": {},
   "source": [
    "Print the type of 1 of these objects.\n",
    "\n",
    "Print the .text attribute of each of these objects.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "52594f69",
   "metadata": {},
   "outputs": [],
   "source": [
    "from bs4 import BeautifulSoup\n",
    "\n",
    "scrapee = '../dormouse.html'\n",
    "\n",
    "text = open(scrapee).read()\n",
    "\n",
    "soup = BeautifulSoup(text, 'html.parser')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "984a6cba",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d17ad353",
   "metadata": {},
   "source": [
    "<B>3.20:  <U>Access tag by parameter using a dict</U>.  Use a dict with <B>.find()</B> to specify a 'class' parameter value (e.g. <B>attrs={'class': 'story\\_title'}</B>)</B>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a02e3f74",
   "metadata": {},
   "outputs": [],
   "source": [
    "from bs4 import BeautifulSoup\n",
    "\n",
    "scrapee = '../dormouse.html'\n",
    "\n",
    "text = open(scrapee).read()\n",
    "\n",
    "soup = BeautifulSoup(text, 'html.parser')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3de5290f",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cda5fdd2",
   "metadata": {},
   "source": [
    "<B>3.21:  <U>individual parameter values</U>:  for a tag that has them, use a subscript to access parameter values of a tag (e.g. <B>tag['value']</b> for the first meta tag)</B>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f0963658",
   "metadata": {},
   "outputs": [],
   "source": [
    "from bs4 import BeautifulSoup\n",
    "\n",
    "scrapee = '../dormouse.html'\n",
    "\n",
    "text = open(scrapee).read()\n",
    "\n",
    "soup = BeautifulSoup(text, 'html.parser')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e0bf3cdd",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "87ba18dd",
   "metadata": {},
   "source": [
    "<B>3.22:  <U>Find all parameter values</U>:  for those tags that have them, use <B>.find\\_all()</B> to access multiple tags with the same criteria.  </B>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f5b421f7",
   "metadata": {},
   "outputs": [],
   "source": [
    "from bs4 import BeautifulSoup\n",
    "\n",
    "scrapee = '../dormouse.html'\n",
    "\n",
    "text = open(scrapee).read()\n",
    "\n",
    "soup = BeautifulSoup(text, 'html.parser')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e0e3ddda",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c6a4cd57",
   "metadata": {},
   "source": [
    "LAB"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4e9893ad",
   "metadata": {},
   "source": [
    "The following exercises will parse the <B>test\\_scrape.html</B> page in this week's session folder.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e4d45a74",
   "metadata": {},
   "source": [
    "<pre style=\"margin: 0; padding=0\"><DIV style=\"font-family: Courier; border: 1px solid #dbdbdb; padding: 7px\">&lt;html&gt;\n",
    "  &lt;head&gt;\n",
    "    &lt;title&gt;This is a page title.&lt;/title&gt;\n",
    "  &lt;/head&gt;\n",
    "  &lt;body&gt;\n",
    "    &lt;h3 class=\"heading\"&gt;This is a page heading.&lt;/h3&gt;\n",
    "    &lt;p&gt;This is some text.&lt;/p&gt;\n",
    "    &lt;p&gt;This is some more text.&lt;/p&gt;\n",
    "    &lt;h3 class=\"midpage\"&gt;This is a midpage heading.&lt;/h3&gt;\n",
    "    &lt;p&gt;This is even more text.&lt;/p&gt;\n",
    "    &lt;div content=\"Some div parameter content we want!\"&gt;\n",
    "    Some div text!\n",
    "    &lt;/div&gt;\n",
    "  &lt;/body&gt;\n",
    "&lt;/html&gt;</DIV></pre>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7573b3e3",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8f1df1a6",
   "metadata": {},
   "source": [
    "<div style=\"background-color: #ccffcc; padding: 10px; border: 2px solid green\"><B>3.23:  In <B>test\\_scrape.html</B>, scrape the page title (the title within the &lt;title&gt; tags) and print it.</B></div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6427a999",
   "metadata": {},
   "outputs": [],
   "source": [
    "from bs4 import BeautifulSoup\n",
    "\n",
    "fname = '../test_scrape.html'\n",
    "\n",
    "fh = open(fname)\n",
    "text = fh.read()\n",
    "\n",
    "soup = BeautifulSoup(text, 'html.parser')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bdc848dc",
   "metadata": {},
   "source": [
    "<U>Expected output</U>:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a8ff3577",
   "metadata": {},
   "outputs": [],
   "source": [
    "This is a page title."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ce12681d",
   "metadata": {},
   "source": [
    "Note that you may occasionally encounter a <B>UnicodeDecodeError</B> when you attempt to read a file from the internet.  In these cases you should tell Python which encoding to use:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2f94f540",
   "metadata": {},
   "outputs": [],
   "source": [
    "text = open(scrapee, encoding='utf-8')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ab6e7f9f",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f48819b1",
   "metadata": {},
   "source": [
    "<div style=\"background-color: #ccffcc; padding: 10px; border: 2px solid green\"><B>3.24:  Scrape and print the &lt;h3&gt; tag in the middle of the page (not the first <B>&lt;h3&gt;</B> tag)</B></div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "85ee8280",
   "metadata": {},
   "outputs": [],
   "source": [
    "from bs4 import BeautifulSoup\n",
    "\n",
    "fname = '../test_scrape.html'\n",
    "\n",
    "fh = open(fname)\n",
    "text = fh.read()\n",
    "\n",
    "soup = BeautifulSoup(text, 'html.parser')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "efdd0d3c",
   "metadata": {},
   "source": [
    "<U>Expected Output</U>:"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f9045678",
   "metadata": {},
   "source": [
    "<pre style=\"margin: 0; padding=0\"><DIV style=\"font-family: Courier; border: 1px solid #dbdbdb; padding: 7px\">This is a midpage heading.</DIV></pre>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6a93ef42",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e2905080",
   "metadata": {},
   "source": [
    "<div style=\"background-color: #ccffcc; padding: 10px; border: 2px solid green\"><B>3.25:  Scrape and print the &lt;div&gt; text as well as the <B>\"content\"</B> parameter value.  </B></div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9175a68a",
   "metadata": {},
   "outputs": [],
   "source": [
    "from bs4 import BeautifulSoup\n",
    "\n",
    "fname = '../test_scrape.html'\n",
    "\n",
    "fh = open(fname)\n",
    "text = fh.read()\n",
    "\n",
    "soup = BeautifulSoup(text, 'html.parser')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5f95d426",
   "metadata": {},
   "source": [
    "<U>Expected Output</U>:"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3f2a67fe",
   "metadata": {},
   "source": [
    "<pre style=\"margin: 0; padding=0\"><DIV style=\"font-family: Courier; border: 1px solid #dbdbdb; padding: 7px\">Some div parameter content we want!\n",
    "\n",
    "    Some div text!\n",
    "</DIV></pre>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "185019b1",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d82779e2",
   "metadata": {},
   "source": [
    "<div style=\"background-color: #ccffcc; padding: 10px; border: 2px solid green\"><B>3.26:  Scrape and print each of the &lt;p&gt; tag texts.  </B></div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "52133f84",
   "metadata": {},
   "outputs": [],
   "source": [
    "from bs4 import BeautifulSoup\n",
    "\n",
    "fname = '../test_scrape.html'\n",
    "\n",
    "fh = open(fname)\n",
    "text = fh.read()\n",
    "\n",
    "soup = BeautifulSoup(text, 'html.parser')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "69a285f6",
   "metadata": {},
   "source": [
    "<U>Expected Output</U>:"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6b715b7f",
   "metadata": {},
   "source": [
    "<pre style=\"margin: 0; padding=0\"><DIV style=\"font-family: Courier; border: 1px solid #dbdbdb; padding: 7px\">This is some text.\n",
    "This is some more text.\n",
    "This is even more text.</DIV></pre>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1f32a05b",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a75287f8",
   "metadata": {},
   "source": [
    "WORKING WITH ENCODINGS AND UNICODE"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9ae0477e",
   "metadata": {},
   "source": [
    "<B>3.27:  <U>Use ord() and chr() to encode characters to integers and decode integers to characters</U>.</B>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "100104c6",
   "metadata": {},
   "source": [
    "Use the <B>ord()</B> function to convert this character to an integer; then use the <B>chr()</B> function to convert back from integer to character."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6f9973cf",
   "metadata": {},
   "outputs": [],
   "source": [
    "char = 'A'\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d222d611",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b99a83ae",
   "metadata": {},
   "source": [
    "<B>3.28:  <U>Demonstratin:  note how you can use integers to retrieve characters</U>.  </B>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6bcf17d2",
   "metadata": {},
   "source": [
    "You can use integers to retrieve characters.  Run the following program:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "538910a6",
   "metadata": {},
   "outputs": [],
   "source": [
    "for idx in range(65, 70):\n",
    "    print(chr(idx))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c4ef3a97",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8f07ada5",
   "metadata": {},
   "source": [
    "<B>3.29:  <U>Use str.encode() and bytes.decode() to convert a string to a bytestring and back to string</U>.</B>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f576e3b5",
   "metadata": {},
   "source": [
    "<B>greet.encode()</B> should include an encoding ('ascii', 'latin-1' or 'utf-8'):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "436a1fcb",
   "metadata": {},
   "outputs": [],
   "source": [
    "greet = 'Hello, world!'\n",
    "\n",
    "bytestr = greet.encode(# add encoding here)\n",
    "print(bytestr)\n",
    "\n",
    "# subscript the bytestring to see individual characters\n",
    "\n",
    "\n",
    "\n",
    "# now call bytestr.decode() with the same encoding to see the string again\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6349279d",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ae20645c",
   "metadata": {},
   "source": [
    "<B>3.30:  <U>Encode a latin-1 string to bytes and back to string, then try to encode as ascii</U></B>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "41896105",
   "metadata": {},
   "source": [
    "The below string contains a non-ascii character.  Encode into the following encodings:  'latin-1', 'utf-8' and 'ascii'.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "411e7032",
   "metadata": {},
   "outputs": [],
   "source": [
    "string = 'voilà'\n",
    "\n",
    "bytestr = string.encode(# add encoding here)\n",
    "\n",
    "print(bytestr)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "db69719d",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6ee206c2",
   "metadata": {},
   "source": [
    "<B>3.31:  <U>Open a file in various encodings</U>.  The text of the following file is French, and we are opening it in utf-8 (Python's default).  Try to open the file with <B>encoding='latin-1'</B> and <B>encoding='ascii'</B>.  </B>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "49744ca9",
   "metadata": {},
   "outputs": [],
   "source": [
    "filename = '../la_vie.txt'\n",
    "\n",
    "fh = open(filename, encoding='utf-8')\n",
    "\n",
    "print(fh.read())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d4e66d12",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f3de0157",
   "metadata": {},
   "source": [
    "<B>3.32:  <U>Use the <B>chardet</B> library to \"sniff\" an encoding</U>.  Given the below strings, use <B>chardet.detect()</B> with each of the two bytestring to get Python's best guess as to its encoding.  Print the resulting dict from <B>.detect()</B>.  </B>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c214e9cd",
   "metadata": {},
   "outputs": [],
   "source": [
    "import chardet\n",
    "\n",
    "bytestr1 = 'voilà'.encode('utf-8')\n",
    "\n",
    "bytestr2 = 'hello'.encode('utf-8')\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "928fc151",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2a7a170c",
   "metadata": {},
   "source": [
    "optional:  FLASK"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "92bb6550",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5b441378",
   "metadata": {},
   "source": [
    "In these exercises, we'll re-create a Flask application that takes form input and displays an image.\n",
    "\n",
    "You can supplement these instructions with your own application idea -- one that uses user input to choose and display images."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8cc8006b",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c2824dff",
   "metadata": {},
   "source": [
    "<B>3.33:  Create a simple Flask 'hello world' app that greets the user, and start the application.</B>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "de826e84",
   "metadata": {},
   "source": [
    "Use the basic <B>hello\\_flask.py</B> example.\n",
    "\n",
    "Start the application by running it from the command line (the Terminal or Command Prompt window).\n",
    "\n",
    "<U>Expected Output</U>:"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "77feea5b",
   "metadata": {},
   "source": [
    "<pre style=\"margin: 0; padding=0\"><DIV style=\"font-family: Courier; border: 1px solid #dbdbdb; padding: 7px\">$ ./hello.py\n",
    " * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)\n",
    " * Restarting with stat\n",
    " * Debugger is active!\n",
    " * Debugger PIN: 323-629-461</DIV></pre>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c38accbd",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5341d00c",
   "metadata": {},
   "source": [
    "<B>3.34:  Call the application from a browser.</B>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "16485adf",
   "metadata": {},
   "source": [
    "Call the application from a browser with the following URL; you should see \"Hello, World!\" displayed in the browser.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "61be4167",
   "metadata": {},
   "source": [
    "<pre style=\"margin: 0; padding=0\"><DIV style=\"font-family: Courier; border: 1px solid #dbdbdb; padding: 7px\">http://localhost:5000/hello</DIV></pre>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f673b6a4",
   "metadata": {},
   "source": [
    "<U>Expected Output</U>:"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "90b3b43b",
   "metadata": {},
   "source": [
    "<pre style=\"margin: 0; padding=0\"><DIV style=\"font-family: Courier; border: 1px solid #dbdbdb; padding: 7px\">Hello, world!</DIV></pre>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2320971c",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cbe32092",
   "metadata": {},
   "source": [
    "<B>3.35:  (Exploratory exercise):  view log messages at command line.  </B>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "836baaa8",
   "metadata": {},
   "source": [
    "The sample code from the <B>hello world</B> app contains a <B>print()</B> statement.  Look in the Terminal or Command Prompt window to see the print output displayed.\n",
    "\n",
    "Refresh the page several times so you can see that the log message is displayed.\n",
    "<U>Sample program run</U>:"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3343c160",
   "metadata": {},
   "source": [
    "<pre style=\"margin: 0; padding=0\"><DIV style=\"font-family: Courier; border: 1px solid #dbdbdb; padding: 7px\">*** DEBUG:  inside hello_world() ***\n",
    "127.0.0.1 - - [24/Mar/2018 13:45:59] \"GET /hello HTTP/1.1\" 200 -\n",
    "*** DEBUG:  inside hello_world() ***\n",
    "127.0.0.1 - - [24/Mar/2018 13:45:59] \"GET /hello HTTP/1.1\" 200 -\n",
    "*** DEBUG:  inside hello_world() ***\n",
    "127.0.0.1 - - [24/Mar/2018 13:46:00] \"GET /hello HTTP/1.1\" 200 -</DIV></pre>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b5467d53",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8d84d258",
   "metadata": {},
   "source": [
    "<B>3.36:  Add another <B>@app.route()</B> function. </B>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8d2eb0b6",
   "metadata": {},
   "source": [
    "Add another <B>@app.route()</B> function that says \"Goodbye, now!  Come on back, y'hear?\".  This function should be called when the user adds <B>/goodbye</B> to the URL.\n",
    "\n",
    "Call the new URL:"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9975b977",
   "metadata": {},
   "source": [
    "<pre style=\"margin: 0; padding=0\"><DIV style=\"font-family: Courier; border: 1px solid #dbdbdb; padding: 7px\">http://localhost:5000/goodbye</DIV></pre>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "185cba1a",
   "metadata": {},
   "source": [
    "<U>Expected Output</U>:"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "17466862",
   "metadata": {},
   "source": [
    "<pre style=\"margin: 0; padding=0\"><DIV style=\"font-family: Courier; border: 1px solid #dbdbdb; padding: 7px\">Goodbye, now!  Come on back, y'hear?</DIV></pre>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0278d8af",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "58b20859",
   "metadata": {},
   "source": [
    "<B>3.37:  Add templates for <B>/hello</B> and <B>/goodbye</B> so that when the user visits, it returns a template rather than a string.  </B>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f4945ae3",
   "metadata": {},
   "source": [
    "The templates must be placed within a folder called <B>template/</B> that is in the same directory as the script.\n",
    "\n",
    "Here is the template to add for hello (<B>hello.html</B>, included in this session's files):"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "147c1887",
   "metadata": {},
   "source": [
    "<pre style=\"margin: 0; padding=0\"><DIV style=\"font-family: Courier; border: 1px solid #dbdbdb; padding: 7px\">&lt;html&gt;\n",
    "  &lt;head&gt;&lt;title&gt;A Greeting&lt;/title&gt;&lt;/head&gt;\n",
    "  &lt;body&gt;\n",
    "      &lt;h1&gt;Hello, Template!&lt;/h1&gt;\n",
    "  &lt;/body&gt;\n",
    "&lt;/html&gt;</DIV></pre>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ddfa151d",
   "metadata": {},
   "source": [
    "<U>Expected Output</U>:"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7b6a366f",
   "metadata": {},
   "source": [
    "<pre style=\"margin: 0; padding=0\"><DIV style=\"font-family: Courier; border: 1px solid #dbdbdb; padding: 7px\">Hello, Template!</DIV></pre>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "87366424",
   "metadata": {},
   "source": [
    "Here is the template to add for goodbye (<B>goodbye.html</B>, included in this session's files):"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f531db33",
   "metadata": {},
   "source": [
    "<pre style=\"margin: 0; padding=0\"><DIV style=\"font-family: Courier; border: 1px solid #dbdbdb; padding: 7px\">&lt;html&gt;\n",
    "  &lt;head&gt;&lt;title&gt;A Farewell&lt;/title&gt;&lt;/head&gt;\n",
    "  &lt;body&gt;\n",
    "      &lt;h1&gt;Goodbye, now!  Come on back, y'hear?!&lt;/h1&gt;\n",
    "  &lt;/body&gt;\n",
    "&lt;/html&gt;</DIV></pre>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "540fa539",
   "metadata": {},
   "source": [
    "<U>Expected Output</U>:"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "268de887",
   "metadata": {},
   "source": [
    "<pre style=\"margin: 0; padding=0\"><DIV style=\"font-family: Courier; border: 1px solid #dbdbdb; padding: 7px\">Goodbye, now!  Come on back, y'hear?!</DIV></pre>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e19fa931",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8ceb37b6",
   "metadata": {},
   "source": [
    "<B>3.38:  Add a \"static\" HTML page with a link that calls the <B>hello/</B> function, and another link that calls the <B>goodbye/</B> function.  </B>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "378f6007",
   "metadata": {},
   "source": [
    "This page has been added as <B>launch.html</B>, also in the <B>templates/</B> directory.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5548be65",
   "metadata": {},
   "source": [
    "<pre style=\"margin: 0; padding=0\"><DIV style=\"font-family: Courier; border: 1px solid #dbdbdb; padding: 7px\">&lt;html&gt;\n",
    "  &lt;head&gt;&lt;title&gt;Launch&lt;/title&gt;&lt;/head&gt;\n",
    "  &lt;body&gt;\n",
    "    &lt;h1&gt;Launch!&lt;/h1&gt;\n",
    "    &lt;A HREF=\"http://localhost:5000/hello\"&gt;say hello&lt;/A&gt;&lt;br&gt;&lt;br&gt;\n",
    "    &lt;A HREF=\"http://localhost:5000/goodbye\"&gt;say goodbye&lt;/A&gt;\n",
    "  &lt;/body&gt;\n",
    "&lt;/html&gt;</DIV></pre>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3526680f",
   "metadata": {},
   "source": [
    "As you can see, each link points to another place in the app.\n",
    "\n",
    "After saving this page as <B>launch.html</B>, use your browser's <B>File > Open File...</B> to navigate to the page and display it.  You'll see the two links displayed.\n",
    "\n",
    "<U>Expected output</U>:\n",
    "Click on each one to see that the page calls the Flask app and displays the proper template."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5b187c1b",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fa074b18",
   "metadata": {},
   "source": [
    "<B>3.39:  Add a link on the <B>hello/</B> page that calls the <B>goodbye/</B> page, and one on the <B>goodbye/</B> page that calls the <B>hello/</B> page.</B>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "11789623",
   "metadata": {},
   "source": [
    "However, don't use the <B>&lt;A HREF=</B> URL as was done in the launch page.  Instead, use the <B>flask.url\\_for()</B> function and allow Flask to build the URL for you:"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "44364a3d",
   "metadata": {},
   "source": [
    "<pre style=\"margin: 0; padding=0\"><DIV style=\"font-family: Courier; border: 1px solid #dbdbdb; padding: 7px\">&lt;A HREF=\"{{ url_for('hello_world') }}\"&gt;say goodbye&lt;/A&gt;</DIV></pre>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7dda155f",
   "metadata": {},
   "source": [
    "Also make special note that the argument to <B>url\\_for()</B> is <I>the name of the function</I>, not the <B>@app.route()</B> URL string.\n",
    "\n",
    "<U>Expected output</U>:\n",
    "You should be able to click back and forth between one page and another by clicking the link on each page."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "651b52e2",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "de7d82af",
   "metadata": {},
   "source": [
    "<B>3.40:  Add the following form to the <B>hello.html</B> template, which features a <B>&lt;select&gt;</B> dropdown and and an <B>&lt;input&gt;</B> field.  Call the app through the form by submitting the form.  </B>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0caa910f",
   "metadata": {},
   "source": [
    "<pre style=\"margin: 0; padding=0\"><DIV style=\"font-family: Courier; border: 1px solid #dbdbdb; padding: 7px\">    &lt;form action=\"<B>http://localhost:5000/goodbye</B>\"&gt;\n",
    "\n",
    "    Please enter a caption:  &lt;input type=\"text\" name=\"caption\"&gt;\n",
    "    &lt;br&gt;\n",
    "\n",
    "    Please select a mood:\n",
    "    &lt;select name=\"mood\"&gt;\n",
    "        &lt;option&gt;happy&lt;/option&gt;\n",
    "        &lt;option&gt;sad&lt;/option&gt;\n",
    "    &lt;/select&gt;\n",
    "    &lt;br&gt;\n",
    "\n",
    "        &lt;input type=\"submit\"&gt;\n",
    "    &lt;/form&gt;</DIV></pre>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "20f4f37c",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "60f5e5e3",
   "metadata": {},
   "source": [
    "<B>3.41:  Read the <B>caption</B> and <B>mood</B> field values and include them in the <B>goodbye.html</B> template.  </B>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "29bfdcdf",
   "metadata": {},
   "source": [
    "The form sends field values for \"caption\" and \"mood\" to the app when it calls the <B>goodbye/</B> URL; retrieve these values using <B>flask.request.args.get('caption')</B> and <B>flask.request.args.get('mood')</B>.\n",
    "\n",
    "Use the <B>{{ [token name] }}</B> token (where <B>[token\\_name]</B> is the token name) to insert a value into the template.  Add parameter arguments (for example <B>caption=[caption variable]</B>, where <B>[caption variable]</B> is whatever variable you used to retrieve the value from the form) to <B>render\\_template()</B> to insert the value.\n",
    "\n",
    "<U>Expected Output</U>:"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f78c9bce",
   "metadata": {},
   "source": [
    "<pre style=\"margin: 0; padding=0\"><DIV style=\"font-family: Courier; border: 1px solid #dbdbdb; padding: 7px\">Goodbye, now! Come on back, y'hear?!\n",
    "\n",
    "caption: Hi there (or whatever you typed into form)\n",
    "mood: happy (or whichever mood you chose)\n",
    "say hello</DIV></pre>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9d72f75f",
   "metadata": {},
   "source": [
    "Note that <B>Hi there</B> and <B>happy</B> are values that I entered into the form when I submitted it."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c7bfaef8",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b248b96b",
   "metadata": {},
   "source": [
    "<B>3.42:  Add an image to the <B>goodbye</B> page.  </B>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8701122f",
   "metadata": {},
   "source": [
    "Add the <B>happup.jpg</B> image to the <B>goodbye.html</B> template.\n",
    "\n",
    "In order to reference images in an HTML page served by flask, we must put the images in <B>static/images</B> and reference them using <B>&lt;IMG SRC=\"{{ url\\_for('static', filename='images/[name of image file]') }}\"&gt;</B>.\n",
    "\n",
    "<U>Expected Output</U>:\n",
    "You should see the <B>happup.jpg</B> image along with the form input values"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "29003ac9",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a796f50e",
   "metadata": {},
   "source": [
    "<B>3.43:  Choose an image based on the user's dropdown choice.  </B>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d3ce6386",
   "metadata": {},
   "source": [
    "Now add the <B>sadpup.jpg</B> image to the <B>static/images/</B> directory and modify the script so that it sends either image name to the template based on the user's \"mood\" choice.\n",
    "\n",
    "Use the <B>{% if [varname] == [value] %}  {% else %}  {% endif %}</B> construct to have the template show either the <B>happup.jpg</B> or <B>sadpup.jpg</B> image.\n",
    "\n",
    "Also, place the <B>caption</B> string beneath the image.\n",
    "\n",
    "<U>Expected Output</U>:\n",
    "You should see the <B>happup.jpg</B> or <B>sadpup.jpg</B> image displayed along with a caption beneath."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "db3e953b",
   "metadata": {},
   "source": [
    " "
   ]
  }
 ],
 "metadata": {},
 "nbformat": 4,
 "nbformat_minor": 5
}
