--- title: "Python Urllib ⬇📜" date: 2021-10-26T20:02:07+02:00 draft: false toc: true tags: - python - scraping - code --- I had to pull some meta data from a media data base and since this tends to be a go to setup when I use urllib with python. I thought I would make a quick note regarding cookies and making POST/GET requests accordingly. ## Setting up a HTTP session The urllib python library allows you to get global session parameters directly by calling the `build_opener` and `install_opener` methods accordingly. Usually if you make HTTP requests with empty headers or little to no session data any script will tend to be blocked when robots are not welcome so while setting these parameters mitigates such an issue it is advised to be a responsible end-user. ```python mycookies = http.cookiejar.MozillaCookieJar() mycookies.load("cookies.txt") opener = urllib.request.build_opener( urllib.request.HTTPCookieProcessor(mycookies) ) opener.addheaders = [ ( "User-agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36" + "(KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36", ), ( "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9," + "image/avif,image/webp,image/apng,*/*;q=0.8," + "application/signed-exchange;v=b3;q=0.9", ), ] urllib.request.install_opener(opener) ``` The above code snippet sets a user agent and what kind of data the session is willing to accept. This is generic and simply taken from one of my own browser sessions. Additionally I load in `cookies.txt` which are the session cookies that I exported to a file for a given domain from my browser. ## HTTP POST request Web based APIs will have various methods for interacting but POST requests with JSON type input/output and occasionally XML but given python's native support for JSON this is generally the way to do things. ``` python url = f"{host_name}/api.php" data = json.dumps(post_data).encode() req = urllib.request.Request(url, data=data) meta = urllib.request.urlopen(req) return json.loads(meta.read()) ``` The above code snippet prepares a `req` object for particular `host_name` and `post_data` which is a dictionary that is encoded to a JSON string. Calling urlopen on this request will perform a POST request accordingly where if all works as expected should return a JSON string that is mapped to a python collection. In the scenario where the data is returned as an XML string / document, there is a `xmltodict` python library that will return a python collection. The downside here is the xml has quite a deep hierarchy that is difficult to appreciate unless the we get into large xml data structures that can be queried. For reference the xml parsing will look something like this: ```python xmltodict.parse(meta.read()) ``` ## HTTP GET request with BeautifulSoup Performing GET requests is usually much much most simply since you just need to determine the appropriate url. Here I included an example where the `BeautifulSoup` python library is used to container the HTTP response and search through any links within the response that march a regular expression. ```python query_url = f"{host_name}/?f_search={tag_name}" resp_data = urllib.request.urlopen(query_url) resp_soup = BeautifulSoup(resp_data) return [ link["href"] for link in resp_soup.find_all("a", href=True) if re.match( f"{host_name}/g/([0-9a-z]+)/([0-9a-z]+)", link["href"] ) ] ``` This is probably the most common use case for the `BeautifulSoup` library and it is very effective instead of sifting through any html data. ## Cloudflare Hosted Domains A number sites will be hosted/backed by Cloudflare that tend to keep track of the user session in combination with the session cookies. This means that by-passing the anti-bot measures is slightly more inconvienient than usual. Fortunately there are a few python-libraries that help to set the request headers correctly.