{"id":311,"date":"2023-05-09T14:11:41","date_gmt":"2023-05-09T14:11:41","guid":{"rendered":"https:\/\/iris.siue.edu\/stldigitalhumanities\/?p=311"},"modified":"2025-11-21T17:02:21","modified_gmt":"2025-11-21T17:02:21","slug":"using-ai-for-webscraping","status":"publish","type":"post","link":"https:\/\/iris.siue.edu\/stldigitalhumanities\/2023\/05\/09\/using-ai-for-webscraping\/","title":{"rendered":"Using AI for Webscraping"},"content":{"rendered":"\n<p><strong>Contributed by Montaque Reynolds, Saint Louis University<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Difficulty: <\/strong><\/li>\n\n\n\n<li><strong>Field:<\/strong> <\/li>\n\n\n\n<li><strong>Tools and resources: <\/strong><\/li>\n<\/ul>\n\n\n\n<p>I wondered if I could useChatGPT to develop a webscraper for genius.com that I\u2019ve been struggling with for some time. It turns out that I could. Here is the process and resulting code. This walkthrough demonstrates the iterative process of co-writing code with an AI.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Prompt<\/h5>\n\n\n\n<p>how do I scrape&nbsp;<a href=\"https:\/\/genius.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/genius.com<\/a>&nbsp;in python<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">ChaptGPT<\/h5>\n\n\n\n<p>To scrape data from&nbsp;<a href=\"https:\/\/genius.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/genius.com<\/a>&nbsp;in Python, you can use web scraping libraries such as Beautiful Soup and Requests. Here\u2019s an example of how you can scrape the lyrics of a song from Genius.com:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\n\n\n\n<strong>import<\/strong>&nbsp;requests\n<strong>from<\/strong>&nbsp;bs4 <strong>import<\/strong>&nbsp;BeautifulSoup\n\n<em># Replace the URL with the Genius.com URL of the song you want to scrape<\/em>\nurl = 'https:\/\/genius.com\/Billie-eilish-bad-guy-lyrics'\n\n<em># Make a GET request to the URL<\/em>\nresponse = requests.get(url)\n\n<em># Parse the HTML content using Beautiful Soup<\/em>\nsoup = BeautifulSoup(response.content, 'html.parser')\n\n<em># Find the div element that contains the lyrics<\/em>\nlyrics_div = soup.find('div', class_='lyrics')\n\n<em># Get the text of the lyrics<\/em>\nlyrics = lyrics_div.get_text()\n\n<em># Print the lyrics<\/em>\nprint(lyrics)\n<\/code><\/pre>\n\n\n\n<p>This code will scrape the lyrics of the song \u201cbad guy\u201d by Billie Eilish from Genius.com and print them to the console. Note that scraping websites may violate their terms of service, so use this code at your own risk.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Prompt<\/h5>\n\n\n\n<p>That did not work<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">ChaptGPT<\/h5>\n\n\n\n<p>I apologize if the previous code did not work for you. There can be several reasons why the code did not work, such as changes in the website\u2019s HTML structure or blocking of the requests by the website. Here is an updated code that may work for you:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\n\n\n\n<strong>import<\/strong>&nbsp;requests\n<strong>from<\/strong>&nbsp;bs4 <strong>import<\/strong>&nbsp;BeautifulSoup\n\n<em># Set the URL of the page you want to scrape<\/em>\nurl = \"https:\/\/genius.com\/Billie-eilish-bad-guy-lyrics\"\n\n<em># Set the headers to avoid blocking of requests<\/em>\nheaders = {\n&nbsp; &nbsp; \"User-Agent\": \"Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/58.0.3029.110 Safari\/537.3\"}\n\n<em># Send a GET request to the URL with headers<\/em>\nresponse = requests.get(url, headers=headers)\n\n<em># Create a BeautifulSoup object to parse the HTML content<\/em>\nsoup = BeautifulSoup(response.content, \"html.parser\")\n\n<em># Find the lyrics div tag<\/em>\nlyrics_div = soup.find(\"div\", class_=\"lyrics\")\n\n<em># Extract the text from the lyrics div tag<\/em>\nlyrics = lyrics_div.get_text()\n\n<em># Print the lyrics<\/em>\nprint(lyrics)\n<\/code><\/pre>\n\n\n\n<p>This updated code sets the User-Agent header to avoid blocking of requests by the website. If the website still blocks your requests, you may need to use a proxy server or consider using the Genius API instead of web scraping.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Prompt<\/h5>\n\n\n\n<p>I do have a genius api<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">ChatGPT<\/h5>\n\n\n\n<p>Great! If you have a Genius API, you can use it to programmatically access the data from Genius.com. Here is an example code that shows how to use the Genius API to get the lyrics of a song:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\n\n\n\nimport lyricsgenius\n\n<em># Set the access token for the Genius API<\/em>\naccess_token = \"&lt;your_access_token&gt;\"\n\n<em># Create a Genius object with the access token<\/em>\ngenius = lyricsgenius.Genius(access_token)\n\n<em># Set the name of the artist and the title of the song you want to get the lyrics for<\/em>\nartist_name = \"Billie Eilish\"\nsong_title = \"bad guy\"\n\n<em># Search for the song on Genius.com<\/em>\nsong = genius.search_song(song_title, artist_name)\n\n<em># Get the lyrics of the song<\/em>\nlyrics = song.lyrics\n\n<em># Print the lyrics<\/em>\nprint(lyrics)\n<\/code><\/pre>\n\n\n\n<p>In this code, you first need to set your access token for the Genius API. Then, you create a Genius object with the access token and search for the song you want to get the lyrics for using the search_song method. Finally, you can get the lyrics of the song using the lyrics attribute of the Song object returned by the search_song method.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Prompt<\/h5>\n\n\n\n<p>Perfect. Now how do I save it to a csv file?<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">ChatGPT<\/h5>\n\n\n\n<p>To save the lyrics to a CSV file, you can use the csv module in Python. Here\u2019s an example of how you can modify the previous code to save the lyrics to a CSV file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\n\n\n\n<strong>import<\/strong>&nbsp;csv\n<strong>import<\/strong>&nbsp;lyricsgenius\n\n<em># Set the access token for the Genius API<\/em>\naccess_token = \"&lt;your_access_token&gt;\"\n\n<em># Create a Genius object with the access token<\/em>\ngenius = lyricsgenius.Genius(access_token)\n\n<em># Set the name of the artist and the title of the song you want to get the lyrics for<\/em>\nartist_name = \"Billie Eilish\"\nsong_title = \"bad guy\"\n\n<em># Search for the song on Genius.com<\/em>\nsong = genius.search_song(song_title, artist_name)\n\n<em># Get the lyrics of the song<\/em>\nlyrics = song.lyrics\n\n<em># Set the filename of the CSV file<\/em>\nfilename = \"lyrics.csv\"\n\n<em># Open the CSV file in write mode<\/em>\n<strong>with<\/strong>&nbsp;open(filename, \"w\", newline=\"\") <strong>as<\/strong>&nbsp;file:\n&nbsp; &nbsp; writer = csv.writer(file)\n\n&nbsp; &nbsp; <em># Write the headers to the CSV file<\/em>\n&nbsp; &nbsp; writer.writerow(&#91;\"Artist\", \"Song Title\", \"Lyrics\"])\n\n&nbsp; &nbsp; <em># Write the data to the CSV file<\/em>\n&nbsp; &nbsp; writer.writerow(&#91;artist_name, song_title, lyrics])\n&nbsp; &nbsp; \nprint(\"Lyrics saved to\", filename)\n<\/code><\/pre>\n\n\n\n<p>In this code, after getting the lyrics of the song, we set the filename of the CSV file and open it in write mode using the with statement. Then, we create a csv.writer object and write the headers to the CSV file using the writerow method. Finally, we write the data (i.e., the artist name, song title, and lyrics) to the CSV file using the writerow method. The newline=\u201c\u201d parameter in the open function call is used to ensure that the rows are separated properly in the CSV file.<\/p>\n\n\n\n<p>After running the code, the lyrics will be saved to the specified CSV file, and a message will be printed to the console indicating the filename where the lyrics are saved.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Prompt<\/h5>\n\n\n\n<p>Great. Now I would like to use it to scrape multiple songs.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">ChatGPT<\/h5>\n\n\n\n<p>To scrape multiple songs using the Genius API, you can use a loop to iterate over a list of songs and write their lyrics to a CSV file. Here\u2019s an example code that shows how you can modify the previous code to scrape the lyrics of multiple songs and save them to a CSV file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\n\n\n\n<strong>import<\/strong>&nbsp;csv\n<strong>import<\/strong>&nbsp;lyricsgenius\n\n<em># Set the access token for the Genius API<\/em>\naccess_token = \"&lt;your_access_token&gt;\"\n\n<em># Create a Genius object with the access token<\/em>\ngenius = lyricsgenius.Genius(access_token)\n\n<em># Set the list of songs you want to get the lyrics for<\/em>\nsongs = &#91;\n&nbsp; &nbsp; {\"artist\": \"Billie Eilish\", \"title\": \"bad guy\"},\n&nbsp; &nbsp; {\"artist\": \"The Weeknd\", \"title\": \"Blinding Lights\"},\n&nbsp; &nbsp; {\"artist\": \"Dua Lipa\", \"title\": \"Levitating\"},\n&nbsp; &nbsp; <em># Add more songs here...<\/em>\n]\n\n<em># Set the filename of the CSV file<\/em>\nfilename = \"lyrics.csv\"\n\n<em># Open the CSV file in write mode<\/em>\n<strong>with<\/strong>&nbsp;open(filename, \"w\", newline=\"\") <strong>as<\/strong>&nbsp;file:\n&nbsp; &nbsp; writer = csv.writer(file)\n\n&nbsp; &nbsp; <em># Write the headers to the CSV file<\/em>\n&nbsp; &nbsp; writer.writerow(&#91;\"Artist\", \"Song Title\", \"Lyrics\"])\n\n&nbsp; &nbsp; <em># Loop over the list of songs and write their lyrics to the CSV file<\/em>\n&nbsp; &nbsp; <strong>for<\/strong>&nbsp;song <strong>in<\/strong>&nbsp;songs:\n&nbsp; &nbsp; &nbsp; &nbsp; <em># Search for the song on Genius.com<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; search_results = genius.search_song(song&#91;\"title\"], song&#91;\"artist\"])\n\n&nbsp; &nbsp; &nbsp; &nbsp; <em># Check if the song was found<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; <strong>if<\/strong>&nbsp;search_results <strong>is<\/strong>&nbsp;<strong>None<\/strong>:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print(f\"{song&#91;'title']} by {song&#91;'artist']} not found on Genius.com\")\n&nbsp; &nbsp; &nbsp; &nbsp; <strong>else<\/strong>:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Get the lyrics of the song<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lyrics = search_results.lyrics\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Write the data to the CSV file<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writer.writerow(&#91;song&#91;\"artist\"], song&#91;\"title\"], lyrics])\n\n<em># Print a message indicating where the lyrics are saved<\/em>\nprint(f\"Lyrics saved to {filename}\")\n<\/code><\/pre>\n\n\n\n<p>In this code, we first set the list of songs we want to get the lyrics for. Each song is represented as a dictionary with keys for the artist and title of the song. Then, we use a loop to iterate over the list of songs and write their lyrics to a CSV file. Inside the loop, we search for the song on Genius.com using the search_song method, and if the song is found, we get its lyrics and write them to the CSV file.<\/p>\n\n\n\n<p>Note that this code assumes that the search_song method returns the first result for each song. If there are multiple search results for a song, you may need to modify the code to select the correct result.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Prompt<\/h5>\n\n\n\n<p>Can you make it skip objects that are not found?<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">ChatGPT<\/h5>\n\n\n\n<p>Sure, you can modify the previous code to skip songs that are not found on Genius.com by adding a condition to check whether the search results are None. Here\u2019s an example of how you can modify the code:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\n\n\n\n<strong>import<\/strong>&nbsp;csv\n<strong>import<\/strong>&nbsp;lyricsgenius\n\n<em># Set the access token for the Genius API<\/em>\naccess_token = \"&lt;your_access_token&gt;\"\n\n<em># Create a Genius object with the access token<\/em>\ngenius = lyricsgenius.Genius(access_token)\n\n<em># Set the list of songs you want to get the lyrics for<\/em>\nsongs = &#91;\n&nbsp; &nbsp; {\"artist\": \"Billie Eilish\", \"title\": \"bad guy\"},\n&nbsp; &nbsp; {\"artist\": \"The Weeknd\", \"title\": \"Blinding Lights\"},\n&nbsp; &nbsp; {\"artist\": \"Dua Lipa\", \"title\": \"Levitating\"},\n&nbsp; &nbsp; <em># Add more songs here...<\/em>\n]\n\n<em># Set the filename of the CSV file<\/em>\nfilename = \"lyrics.csv\"\n\n<em># Open the CSV file in write mode<\/em>\n<strong>with<\/strong>&nbsp;open(filename, \"w\", newline=\"\") <strong>as<\/strong>&nbsp;file:\n&nbsp; &nbsp; writer = csv.writer(file)\n\n&nbsp; &nbsp; <em># Write the headers to the CSV file<\/em>\n&nbsp; &nbsp; writer.writerow(&#91;\"Artist\", \"Song Title\", \"Lyrics\"])\n\n&nbsp; &nbsp; <em># Loop over the list of songs and write their lyrics to the CSV file<\/em>\n&nbsp; &nbsp; <strong>for<\/strong>&nbsp;song <strong>in<\/strong>&nbsp;songs:\n&nbsp; &nbsp; &nbsp; &nbsp; <em># Search for the song on Genius.com<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; search_results = genius.search_song(song&#91;\"title\"], song&#91;\"artist\"])\n\n&nbsp; &nbsp; &nbsp; &nbsp; <em># Check if the song was found<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; <strong>if<\/strong>&nbsp;search_results <strong>is<\/strong>&nbsp;<strong>None<\/strong>:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print(f\"{song&#91;'title']} by {song&#91;'artist']} not found on Genius.com\")\n&nbsp; &nbsp; &nbsp; &nbsp; <strong>else<\/strong>:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Get the lyrics of the song<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lyrics = search_results.lyrics\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Write the data to the CSV file<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writer.writerow(&#91;song&#91;\"artist\"], song&#91;\"title\"], lyrics])\n\n<em># Print a message indicating where the lyrics are saved<\/em>\nprint(f\"Lyrics saved to {filename}\")<\/code><\/pre>\n\n\n\n<p>In this code, we check whether the search_song method returns None using the is operator. If the song is not found, we print a message to the console indicating that the song was not found and skip to the next song in the loop. If the song is found, we get its lyrics and write them to the CSV file as before.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Prompt<\/h5>\n\n\n\n<p>I\u2019m getting a read timeout error<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">ChatGPT<\/h5>\n\n\n\n<p>A read timeout error can occur when the Genius API takes too long to respond to a request. To handle this error, you can add a try-except block around the code that calls the Genius API and retry the request a certain number of times before giving up. Here\u2019s an example of how you can modify the code to handle read timeout errors:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\n\n<strong>import<\/strong>&nbsp;csv\n<strong>import<\/strong>&nbsp;lyricsgenius\n<strong>import<\/strong>&nbsp;time\n\n<em># Set the access token for the Genius API<\/em>\naccess_token = \"&lt;your_access_token&gt;\"\n\n<em># Create a Genius object with the access token<\/em>\ngenius = lyricsgenius.Genius(access_token)\n\n<em># Set the list of songs you want to get the lyrics for<\/em>\nsongs = &#91;\n&nbsp; &nbsp; {\"artist\": \"Billie Eilish\", \"title\": \"bad guy\"},\n&nbsp; &nbsp; {\"artist\": \"The Weeknd\", \"title\": \"Blinding Lights\"},\n&nbsp; &nbsp; {\"artist\": \"Dua Lipa\", \"title\": \"Levitating\"},\n&nbsp; &nbsp; <em># Add more songs here...<\/em>\n]\n\n<em># Set the filename of the CSV file<\/em>\nfilename = \"lyrics.csv\"\n\n<em># Set the maximum number of retries<\/em>\nmax_retries = 3\n\n<em># Open the CSV file in write mode<\/em>\n<strong>with<\/strong>&nbsp;open(filename, \"w\", newline=\"\") <strong>as<\/strong>&nbsp;file:\n&nbsp; &nbsp; writer = csv.writer(file)\n\n&nbsp; &nbsp; <em># Write the headers to the CSV file<\/em>\n&nbsp; &nbsp; writer.writerow(&#91;\"Artist\", \"Song Title\", \"Lyrics\"])\n\n&nbsp; &nbsp; <em># Loop over the list of songs and write their lyrics to the CSV file<\/em>\n&nbsp; &nbsp; <strong>for<\/strong>&nbsp;song <strong>in<\/strong>&nbsp;songs:\n&nbsp; &nbsp; &nbsp; &nbsp; <em># Initialize the retry counter<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; retries = 0\n\n&nbsp; &nbsp; &nbsp; &nbsp; <em># Loop until the request succeeds or the maximum number of retries is reached<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; <strong>while<\/strong>&nbsp;retries &lt; max_retries:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>try<\/strong>:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Search for the song on Genius.com<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; search_results = genius.search_song(song&#91;\"title\"], song&#91;\"artist\"])\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Check if the song was found<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>if<\/strong>&nbsp;search_results <strong>is<\/strong>&nbsp;<strong>None<\/strong>:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print(f\"{song&#91;'title']} by {song&#91;'artist']} not found on Genius.com\")\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>else<\/strong>:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Get the lyrics of the song<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lyrics = search_results.lyrics\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Write the data to the CSV file<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writer.writerow(&#91;song&#91;\"artist\"], song&#91;\"title\"], lyrics])\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Exit the retry loop if the request was successful<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>break<\/strong>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>except<\/strong>&nbsp;Exception <strong>as<\/strong>&nbsp;e:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Print the error message<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print(f\"An error occurred while getting lyrics for {song&#91;'title']} by {song&#91;'artist']}: {e}\")\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Increment the retry counter<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; retries += 1\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Wait for a few seconds before retrying<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; time.sleep(5)\n\n<em># Print a message indicating where the lyrics are saved<\/em>\nprint(f\"Lyrics saved to {filename}\")<\/code><\/pre>\n\n\n\n<p>In this code, we add a try-except block around the code that calls the Genius API, and retry the request a certain number of times before giving up. The maximum number of retries is set using the max_retries variable. If an error occurs while getting the lyrics for a song, we print the error message, increment the retry counter, and wait for a few seconds before retrying the request. Once the request succeeds, we exit the retry loop and write the lyrics to the CSV file as before.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Prompt<\/h5>\n\n\n\n<p>Perfect. Now how do I get it to read the requested songs from a csv file?<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">ChatGPT<\/h5>\n\n\n\n<p>To read the list of songs from a CSV file, you can use Python\u2019s built-in csv module. Here\u2019s an example of how you can modify the code to read the list of songs from a CSV file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\n\n\n<strong>import<\/strong>&nbsp;csv\n<strong>import<\/strong>&nbsp;lyricsgenius\n<strong>import<\/strong>&nbsp;time\n\n<em># Set the access token for the Genius API<\/em>\naccess_token = \"&lt;your_access_token&gt;\"\n\n<em># Create a Genius object with the access token<\/em>\ngenius = lyricsgenius.Genius(access_token)\n\n<em># Set the filename of the input CSV file<\/em>\ninput_filename = \"input_songs.csv\"\n\n<em># Set the filename of the output CSV file<\/em>\noutput_filename = \"output_lyrics.csv\"\n\n<em># Set the maximum number of retries<\/em>\nmax_retries = 3\n\n<em># Open the input CSV file in read mode<\/em>\n<strong>with<\/strong>&nbsp;open(input_filename, \"r\", newline=\"\") <strong>as<\/strong>&nbsp;input_file:\n&nbsp; &nbsp; <em># Create a CSV reader object<\/em>\n&nbsp; &nbsp; reader = csv.reader(input_file)\n\n&nbsp; &nbsp; <em># Skip the header row<\/em>\n&nbsp; &nbsp; next(reader)\n\n&nbsp; &nbsp; <em># Loop over the rows in the input CSV file<\/em>\n&nbsp; &nbsp; songs = &#91;]\n&nbsp; &nbsp; <strong>for<\/strong>&nbsp;row <strong>in<\/strong>&nbsp;reader:\n&nbsp; &nbsp; &nbsp; &nbsp; <em># Parse the artist and song title from the row<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; artist, title = row\n\n&nbsp; &nbsp; &nbsp; &nbsp; <em># Add the song to the list of songs<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; songs.append({\"artist\": artist, \"title\": title})\n\n<em># Open the output CSV file in write mode<\/em>\n<strong>with<\/strong>&nbsp;open(output_filename, \"w\", newline=\"\") <strong>as<\/strong>&nbsp;output_file:\n&nbsp; &nbsp; writer = csv.writer(output_file)\n\n&nbsp; &nbsp; <em># Write the headers to the output CSV file<\/em>\n&nbsp; &nbsp; writer.writerow(&#91;\"Artist\", \"Song Title\", \"Lyrics\"])\n\n&nbsp; &nbsp; <em># Loop over the list of songs and write their lyrics to the output CSV file<\/em>\n&nbsp; &nbsp; <strong>for<\/strong>&nbsp;song <strong>in<\/strong>&nbsp;songs:\n&nbsp; &nbsp; &nbsp; &nbsp; <em># Initialize the retry counter<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; retries = 0\n\n&nbsp; &nbsp; &nbsp; &nbsp; <em># Loop until the request succeeds or the maximum number of retries is reached<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; <strong>while<\/strong>&nbsp;retries &lt; max_retries:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>try<\/strong>:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Search for the song on Genius.com<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; search_results = genius.search_song(song&#91;\"title\"], song&#91;\"artist\"])\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Check if the song was found<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>if<\/strong>&nbsp;search_results <strong>is<\/strong>&nbsp;<strong>None<\/strong>:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print(f\"{song&#91;'title']} by {song&#91;'artist']} not found on Genius.com\")\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>else<\/strong>:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Get the lyrics of the song<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lyrics = search_results.lyrics\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Write the data to the output CSV file<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writer.writerow(&#91;song&#91;\"artist\"], song&#91;\"title\"], lyrics])\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Exit the retry loop if the request was successful<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>break<\/strong>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>except<\/strong>&nbsp;Exception <strong>as<\/strong>&nbsp;e:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Print the error message<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print(f\"An error occurred while getting lyrics for {song&#91;'title']} by {song&#91;'artist']}: {e}\")\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Increment the retry counter<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; retries += 1\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Wait for a few seconds before retrying<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; time.sleep(5)\n\n<em># Print a message indicating where the lyrics are saved<\/em>\nprint(f\"Lyrics saved to {output_filename}\")\n<\/code><\/pre>\n\n\n\n<p>In this code, we open the input CSV file using the csv.reader object and skip the header row. Then, we loop over the rows in the input CSV file and parse the artist and song title from each row. We add each song to the songs list as a dictionary with keys \u201cartist\u201d and \u201ctitle\u201d. Finally, we open the output CSV file using the csv.writer object, loop over the list of songs, and write their lyrics to the output CSV file as before.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Prompt<\/h5>\n\n\n\n<p>Should the headings of the input csv be artist and title?<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">ChatGPT<\/h5>\n\n\n\n<p>Yes, that\u2019s correct. The headings of the input CSV should be \u201cartist\u201d and \u201ctitle\u201d in order for the code to correctly parse the artist and song title from each row.<\/p>\n\n\n\n<p>For example, your input CSV file should look something like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\n\nartist,title\nThe Beatles,Hey Jude\nQueen,Bohemian Rhapsody\nLed Zeppelin,Stairway to Heaven\nThe code I provided assumes that the first row <strong>of<\/strong>&nbsp;the input CSV file contains the column headings \"artist\"&nbsp;<strong>and<\/strong>&nbsp;\"title\", so it skips over <strong>this<\/strong>&nbsp;row using next(reader) <strong>in<\/strong>&nbsp;the <strong>for<\/strong>&nbsp;<strong>loop<\/strong>.\n<\/code><\/pre>\n\n\n\n<h5 class=\"wp-block-heading\">Prompt<\/h5>\n\n\n\n<p>Can you make a copy of this conversation?<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">ChatGPT<\/h5>\n\n\n\n<p>As an AI language model, I do not have the capability to copy the conversation as a whole. However, you can easily copy and save the conversation by selecting all the text and using the copy\/paste function in your browser or text editor.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Prompt<\/h5>\n\n\n\n<p>There is some extra text in some of the lyrics that do not belong<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">ChatGPT<\/h5>\n\n\n\n<p>It\u2019s possible that some of the lyrics retrieved from the Genius API include additional text that is not part of the song lyrics, such as song credits or annotations. One way to remove this extra text is to use regular expressions to identify and remove certain patterns of text.<\/p>\n\n\n\n<p>Here\u2019s an example of how you can modify the code to remove any text in the lyrics that is enclosed in square brackets:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\n\n<strong>import<\/strong>&nbsp;csv\n<strong>import<\/strong>&nbsp;lyricsgenius\n<strong>import<\/strong>&nbsp;re\n<strong>import<\/strong>&nbsp;time\n\n<em># Set the access token for the Genius API<\/em>\naccess_token = \"&lt;your_access_token&gt;\"\n\n<em># Create a Genius object with the access token<\/em>\ngenius = lyricsgenius.Genius(access_token)\n\n<em># Set the filename of the input CSV file<\/em>\ninput_filename = \"input_songs.csv\"\n\n<em># Set the filename of the output CSV file<\/em>\noutput_filename = \"output_lyrics.csv\"\n\n<em># Set the maximum number of retries<\/em>\nmax_retries = 3\n\n<em># Open the input CSV file in read mode<\/em>\n<strong>with<\/strong>&nbsp;open(input_filename, \"r\", newline=\"\") <strong>as<\/strong>&nbsp;input_file:\n&nbsp; &nbsp; <em># Create a CSV reader object<\/em>\n&nbsp; &nbsp; reader = csv.reader(input_file)\n\n&nbsp; &nbsp; <em># Skip the header row<\/em>\n&nbsp; &nbsp; next(reader)\n\n&nbsp; &nbsp; <em># Loop over the rows in the input CSV file<\/em>\n&nbsp; &nbsp; songs = &#91;]\n&nbsp; &nbsp; <strong>for<\/strong>&nbsp;row <strong>in<\/strong>&nbsp;reader:\n&nbsp; &nbsp; &nbsp; &nbsp; <em># Parse the artist and song title from the row<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; artist, title = row\n\n&nbsp; &nbsp; &nbsp; &nbsp; <em># Add the song to the list of songs<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; songs.append({\"artist\": artist, \"title\": title})\n\n<em># Open the output CSV file in write mode<\/em>\n<strong>with<\/strong>&nbsp;open(output_filename, \"w\", newline=\"\") <strong>as<\/strong>&nbsp;output_file:\n&nbsp; &nbsp; writer = csv.writer(output_file)\n\n&nbsp; &nbsp; <em># Write the headers to the output CSV file<\/em>\n&nbsp; &nbsp; writer.writerow(&#91;\"Artist\", \"Song Title\", \"Lyrics\"])\n\n&nbsp; &nbsp; <em># Loop over the list of songs and write their lyrics to the output CSV file<\/em>\n&nbsp; &nbsp; <strong>for<\/strong>&nbsp;song <strong>in<\/strong>&nbsp;songs:\n&nbsp; &nbsp; &nbsp; &nbsp; <em># Initialize the retry counter<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; retries = 0\n\n&nbsp; &nbsp; &nbsp; &nbsp; <em># Loop until the request succeeds or the maximum number of retries is reached<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; <strong>while<\/strong>&nbsp;retries &lt; max_retries:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>try<\/strong>:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Search for the song on Genius.com<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; search_results = genius.search_song(song&#91;\"title\"], song&#91;\"artist\"])\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Check if the song was found<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>if<\/strong>&nbsp;search_results <strong>is<\/strong>&nbsp;<strong>None<\/strong>:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print(f\"{song&#91;'title']} by {song&#91;'artist']} not found on Genius.com\")\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>else<\/strong>:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Get the lyrics of the song<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lyrics = search_results.lyrics\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Remove any text in square brackets from the lyrics<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lyrics = re.sub(r\"\\&#91;(.*?)\\]\", \"\", lyrics)\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Write the data to the output CSV file<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writer.writerow(&#91;song&#91;\"artist\"], song&#91;\"title\"], lyrics])\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Exit the retry loop if the request was successful<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>break<\/strong>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>except<\/strong>&nbsp;Exception <strong>as<\/strong>&nbsp;e:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Print the error message<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print(f\"An error occurred while getting lyrics for {song&#91;'title']} by {song&#91;'artist']}: {e}\")\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Increment the retry counter<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; retries += 1\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Wait for a few seconds before retrying<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; time.sleep(5)\n\n<em># Print a message indicating where the lyrics are saved<\/em>\nprint(f\"Lyrics saved to {output_filename}\")<\/code><\/pre>\n\n\n\n<p>In this modified code, we import the re module to use regular expressions to remove text in square brackets from the lyrics. We then use the re.sub function to replace any text in square brackets with an empty string. This removes any text enclosed in square brackets from the lyrics.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Prompt<\/h5>\n\n\n\n<p>Okay that works, but there is also additional stuff before the [Verse 1]<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">ChatGPT<\/h5>\n\n\n\n<p>It\u2019s possible that the lyrics retrieved from the Genius API include additional text before the actual lyrics begin, such as song credits or annotations. One way to remove this extra text is to use regular expressions to identify and remove certain patterns of text.<\/p>\n\n\n\n<p>Here\u2019s an example of how you can modify the code to remove any text in the lyrics that appears before the first occurrence of a section header (e.g., [Verse 1], [Chorus], etc.):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\n\n\n<strong>import<\/strong>&nbsp;csv\n<strong>import<\/strong>&nbsp;lyricsgenius\n<strong>import<\/strong>&nbsp;re\n<strong>import<\/strong>&nbsp;time\n\n<em># Set the access token for the Genius API<\/em>\naccess_token = \"&lt;your_access_token&gt;\"\n\n<em># Create a Genius object with the access token<\/em>\ngenius = lyricsgenius.Genius(access_token)\n\n<em># Set the filename of the input CSV file<\/em>\ninput_filename = \"input_songs.csv\"\n\n<em># Set the filename of the output CSV file<\/em>\noutput_filename = \"output_lyrics.csv\"\n\n<em># Set the maximum number of retries<\/em>\nmax_retries = 3\n\n<em># Open the input CSV file in read mode<\/em>\n<strong>with<\/strong>&nbsp;open(input_filename, \"r\", newline=\"\") <strong>as<\/strong>&nbsp;input_file:\n&nbsp; &nbsp; <em># Create a CSV reader object<\/em>\n&nbsp; &nbsp; reader = csv.reader(input_file)\n\n&nbsp; &nbsp; <em># Skip the header row<\/em>\n&nbsp; &nbsp; next(reader)\n\n&nbsp; &nbsp; <em># Loop over the rows in the input CSV file<\/em>\n&nbsp; &nbsp; songs = &#91;]\n&nbsp; &nbsp; <strong>for<\/strong>&nbsp;row <strong>in<\/strong>&nbsp;reader:\n&nbsp; &nbsp; &nbsp; &nbsp; <em># Parse the artist and song title from the row<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; artist, title = row\n\n&nbsp; &nbsp; &nbsp; &nbsp; <em># Add the song to the list of songs<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; songs.append({\"artist\": artist, \"title\": title})\n\n<em># Open the output CSV file in write mode<\/em>\n<strong>with<\/strong>&nbsp;open(output_filename, \"w\", newline=\"\") <strong>as<\/strong>&nbsp;output_file:\n&nbsp; &nbsp; writer = csv.writer(output_file)\n\n&nbsp; &nbsp; <em># Write the headers to the output CSV file<\/em>\n&nbsp; &nbsp; writer.writerow(&#91;\"Artist\", \"Song Title\", \"Lyrics\"])\n\n&nbsp; &nbsp; <em># Loop over the list of songs and write their lyrics to the output CSV file<\/em>\n&nbsp; &nbsp; <strong>for<\/strong>&nbsp;song <strong>in<\/strong>&nbsp;songs:\n&nbsp; &nbsp; &nbsp; &nbsp; <em># Initialize the retry counter<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; retries = 0\n\n&nbsp; &nbsp; &nbsp; &nbsp; <em># Loop until the request succeeds or the maximum number of retries is reached<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; <strong>while<\/strong>&nbsp;retries &lt; max_retries:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>try<\/strong>:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Search for the song on Genius.com<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; search_results = genius.search_song(song&#91;\"title\"], song&#91;\"artist\"])\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Check if the song was found<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>if<\/strong>&nbsp;search_results <strong>is<\/strong>&nbsp;<strong>None<\/strong>:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print(f\"{song&#91;'title']} by {song&#91;'artist']} not found on Genius.com\")\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>else<\/strong>:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Get the lyrics of the song<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lyrics = search_results.lyrics\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Remove any text in square brackets from the lyrics<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lyrics = re.sub(r\"\\&#91;(.*?)\\]\", \"\", lyrics)\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Remove any text before the first section header<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; section_header_pattern = r\"\\&#91;.*?\\]\"\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; match = re.search(section_header_pattern, lyrics)\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>if<\/strong>&nbsp;match <strong>is<\/strong>&nbsp;<strong>not<\/strong>&nbsp;<strong>None<\/strong>:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lyrics = lyrics&#91;match.start():]\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Write the data to the output CSV file<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writer.writerow(&#91;song&#91;\"artist\"], song&#91;\"title\"], lyrics])\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Exit the retry loop if the request was successful<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>break<\/strong>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>except<\/strong>&nbsp;Exception <strong>as<\/strong>&nbsp;e:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Print the error message<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print(f\"An error occurred while getting lyrics for {song&#91;'title']} by {song&#91;'artist']}: {e}\")\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Increment the retry counter<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; retries += 1\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Wait for a few seconds before retrying<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; time.sleep(5)\n\n<em># Print a message indicating where the lyrics are saved<\/em>\nprint(f\"Lyrics saved to {output_filename}\")<\/code><\/pre>\n\n\n\n<p>In this modified code, we use the re.search function to find the first occurrence of a section header (e.g., [Verse 1], `[Chorus<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Prompt<\/h5>\n\n\n\n<p>Okay getting there. I also what to remove the text at the beginning of the line that includes \u201c12 ContributorsOne of Them Girls Lyrics\u201d<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">ChatGPT<\/h5>\n\n\n\n<p>You can modify the regular expression to remove any text that occurs before the first section header and also before the line that includes \u201c12 ContributorsOne of Them Girls Lyrics\u201d. Here\u2019s how you can modify the code to do this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\n\n\n<strong>import<\/strong>&nbsp;csv\n<strong>import<\/strong>&nbsp;lyricsgenius\n<strong>import<\/strong>&nbsp;re\n<strong>import<\/strong>&nbsp;time\n\n<em># Set the access token for the Genius API<\/em>\naccess_token = \"&lt;your_access_token&gt;\"\n\n<em># Create a Genius object with the access token<\/em>\ngenius = lyricsgenius.Genius(access_token)\n\n<em># Set the filename of the input CSV file<\/em>\ninput_filename = \"input_songs.csv\"\n\n<em># Set the filename of the output CSV file<\/em>\noutput_filename = \"output_lyrics.csv\"\n\n<em># Set the maximum number of retries<\/em>\nmax_retries = 3\n\n<em># Open the input CSV file in read mode<\/em>\n<strong>with<\/strong>&nbsp;open(input_filename, \"r\", newline=\"\") <strong>as<\/strong>&nbsp;input_file:\n&nbsp; &nbsp; <em># Create a CSV reader object<\/em>\n&nbsp; &nbsp; reader = csv.reader(input_file)\n\n&nbsp; &nbsp; <em># Skip the header row<\/em>\n&nbsp; &nbsp; next(reader)\n\n&nbsp; &nbsp; <em># Loop over the rows in the input CSV file<\/em>\n&nbsp; &nbsp; songs = &#91;]\n&nbsp; &nbsp; <strong>for<\/strong>&nbsp;row <strong>in<\/strong>&nbsp;reader:\n&nbsp; &nbsp; &nbsp; &nbsp; <em># Parse the artist and song title from the row<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; artist, title = row\n\n&nbsp; &nbsp; &nbsp; &nbsp; <em># Add the song to the list of songs<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; songs.append({\"artist\": artist, \"title\": title})\n\n<em># Open the output CSV file in write mode<\/em>\n<strong>with<\/strong>&nbsp;open(output_filename, \"w\", newline=\"\") <strong>as<\/strong>&nbsp;output_file:\n&nbsp; &nbsp; writer = csv.writer(output_file)\n\n&nbsp; &nbsp; <em># Write the headers to the output CSV file<\/em>\n&nbsp; &nbsp; writer.writerow(&#91;\"Artist\", \"Song Title\", \"Lyrics\"])\n\n&nbsp; &nbsp; <em># Loop over the list of songs and write their lyrics to the output CSV file<\/em>\n&nbsp; &nbsp; <strong>for<\/strong>&nbsp;song <strong>in<\/strong>&nbsp;songs:\n&nbsp; &nbsp; &nbsp; &nbsp; <em># Initialize the retry counter<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; retries = 0\n\n&nbsp; &nbsp; &nbsp; &nbsp; <em># Loop until the request succeeds or the maximum number of retries is reached<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; <strong>while<\/strong>&nbsp;retries &lt; max_retries:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>try<\/strong>:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Search for the song on Genius.com<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; search_results = genius.search_song(song&#91;\"title\"], song&#91;\"artist\"])\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Check if the song was found<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>if<\/strong>&nbsp;search_results <strong>is<\/strong>&nbsp;<strong>None<\/strong>:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print(f\"{song&#91;'title']} by {song&#91;'artist']} not found on Genius.com\")\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>else<\/strong>:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Get the lyrics of the song<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lyrics = search_results.lyrics\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Remove any text in square brackets from the lyrics<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lyrics = re.sub(r\"\\&#91;(.*?)\\]\", \"\", lyrics)\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Remove any text before the first section header<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; section_header_pattern = r\"\\&#91;.*?\\]\"\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; match = re.search(section_header_pattern, lyrics)\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>if<\/strong>&nbsp;match <strong>is<\/strong>&nbsp;<strong>not<\/strong>&nbsp;<strong>None<\/strong>:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lyrics = lyrics&#91;match.start():]\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Remove any text before the line that includes \"12 ContributorsOne of Them Girls Lyrics\"<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; contributors_pattern = r\"^.*12 ContributorsOne of Them Girls Lyrics\\n\"\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; match = re.search(contributors_pattern, lyrics)\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>if<\/strong>&nbsp;match <strong>is<\/strong>&nbsp;<strong>not<\/strong>&nbsp;<strong>None<\/strong>:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lyrics = lyrics&#91;match.end():]\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Write the data to the output CSV file<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writer.writerow(&#91;song&#91;\"artist\"], song&#91;\"title\"], lyrics])\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Exit the retry loop if the request was successful<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>break<\/strong>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>except<\/strong>&nbsp;Exception <strong>as<\/strong>&nbsp;e:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Print the error message<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print(f\"An error occurred while getting lyrics for {song&#91;'title']} by {song&#91;'artist']}: {e}\")\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Increment the retry counter<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; retries += 1\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Wait for a few seconds before retrying<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; time.sleep(5)\n\n<em># Print a message indicating where the lyrics are saved<\/em>\nprint(f\"Lyrics saved to {output_filename}\")\n<\/code><\/pre>\n\n\n\n<p>In this modified code, we use the re.search function to find the line that includes \u201c12<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Prompt<\/h5>\n\n\n\n<p>It is a pattern that begins with a number and ends with \u201cLyrics\u201d<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">ChatGPT<\/h5>\n\n\n\n<p>In that case, you can modify the regular expression to match any line that begins with a number and ends with \u201cLyrics\u201d. Here\u2019s how you can modify the code to do this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\n\n\n<strong>import<\/strong>&nbsp;csv\n<strong>import<\/strong>&nbsp;lyricsgenius\n<strong>import<\/strong>&nbsp;re\n<strong>import<\/strong>&nbsp;time\n\n<em># Set the access token for the Genius API<\/em>\naccess_token = \"&lt;your_access_token&gt;\"\n\n<em># Create a Genius object with the access token<\/em>\ngenius = lyricsgenius.Genius(access_token)\n\n<em># Set the filename of the input CSV file<\/em>\ninput_filename = \"input_songs.csv\"\n\n<em># Set the filename of the output CSV file<\/em>\noutput_filename = \"output_lyrics.csv\"\n\n<em># Set the maximum number of retries<\/em>\nmax_retries = 3\n\n<em># Open the input CSV file in read mode<\/em>\n<strong>with<\/strong>&nbsp;open(input_filename, \"r\", newline=\"\") <strong>as<\/strong>&nbsp;input_file:\n&nbsp; &nbsp; <em># Create a CSV reader object<\/em>\n&nbsp; &nbsp; reader = csv.reader(input_file)\n\n&nbsp; &nbsp; <em># Skip the header row<\/em>\n&nbsp; &nbsp; next(reader)\n\n&nbsp; &nbsp; <em># Loop over the rows in the input CSV file<\/em>\n&nbsp; &nbsp; songs = &#91;]\n&nbsp; &nbsp; <strong>for<\/strong>&nbsp;row <strong>in<\/strong>&nbsp;reader:\n&nbsp; &nbsp; &nbsp; &nbsp; <em># Parse the artist and song title from the row<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; artist, title = row\n\n&nbsp; &nbsp; &nbsp; &nbsp; <em># Add the song to the list of songs<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; songs.append({\"artist\": artist, \"title\": title})\n\n<em># Open the output CSV file in write mode<\/em>\n<strong>with<\/strong>&nbsp;open(output_filename, \"w\", newline=\"\") <strong>as<\/strong>&nbsp;output_file:\n&nbsp; &nbsp; writer = csv.writer(output_file)\n\n&nbsp; &nbsp; <em># Write the headers to the output CSV file<\/em>\n&nbsp; &nbsp; writer.writerow(&#91;\"Artist\", \"Song Title\", \"Lyrics\"])\n\n&nbsp; &nbsp; <em># Loop over the list of songs and write their lyrics to the output CSV file<\/em>\n&nbsp; &nbsp; <strong>for<\/strong>&nbsp;song <strong>in<\/strong>&nbsp;songs:\n&nbsp; &nbsp; &nbsp; &nbsp; <em># Initialize the retry counter<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; retries = 0\n\n&nbsp; &nbsp; &nbsp; &nbsp; <em># Loop until the request succeeds or the maximum number of retries is reached<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; <strong>while<\/strong>&nbsp;retries &lt; max_retries:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>try<\/strong>:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Search for the song on Genius.com<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; search_results = genius.search_song(song&#91;\"title\"], song&#91;\"artist\"])\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Check if the song was found<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>if<\/strong>&nbsp;search_results <strong>is<\/strong>&nbsp;<strong>None<\/strong>:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print(f\"{song&#91;'title']} by {song&#91;'artist']} not found on Genius.com\")\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>else<\/strong>:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Get the lyrics of the song<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lyrics = search_results.lyrics\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Remove any text in square brackets from the lyrics<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lyrics = re.sub(r\"\\&#91;(.*?)\\]\", \"\", lyrics)\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Remove any text before the first section header<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; section_header_pattern = r\"\\&#91;.*?\\]\"\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; match = re.search(section_header_pattern, lyrics)\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>if<\/strong>&nbsp;match <strong>is<\/strong>&nbsp;<strong>not<\/strong>&nbsp;<strong>None<\/strong>:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lyrics = lyrics&#91;match.start():]\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Remove any text before the line that includes a number and \"Lyrics\"<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; contributors_pattern = r\"^.*\\d+.*Lyrics\\n\"\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; match = re.search(contributors_pattern, lyrics)\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>if<\/strong>&nbsp;match <strong>is<\/strong>&nbsp;<strong>not<\/strong>&nbsp;<strong>None<\/strong>:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lyrics = lyrics&#91;match.end():]\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Write the data to the output CSV file<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writer.writerow(&#91;song&#91;\"artist\"], song&#91;\"title\"], lyrics])\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Exit the retry loop if the request was successful<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>break<\/strong>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>except<\/strong>&nbsp;Exception <strong>as<\/strong>&nbsp;e:\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Print the error message<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print(f\"An error occurred while getting lyrics for {song&#91;'title']} by {song&#91;'artist']}: {e}\")\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Increment the retry counter<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; retries += 1\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <em># Wait for a few seconds before retrying<\/em>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; time.sleep(5)\n\n<em># Print a message indicating where the lyrics are saved<\/em>\nprint(f\"Lyrics saved to {output_filename}\")<\/code><\/pre>\n\n\n\n<p>In this modified code, we use the regular expression r\u201d^.<em>.<\/em>Lyrics\u201d to match any line that begins with a number.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Prompt<\/h5>\n\n\n\n<p>That worked really well. Thank you.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">ChatGPT<\/h5>\n\n\n\n<p>You\u2019re welcome! I\u2019m glad it worked for you. If you have any more questions or issues, feel free to ask.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Prompt<\/h5>\n\n\n\n<p>could you explain the regular expression in more detail?<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">ChatGPT<\/h5>\n\n\n\n<p>Sure, I\u2019d be happy to explain the regular expression in more detail.<\/p>\n\n\n\n<p>The regular expression r\u201d^.<em>.<\/em>Lyrics\u201d has the following parts:<\/p>\n\n\n\n<p>^: This matches the beginning of the string. .<em>: This matches any character zero or more times. The . matches any character except a newline, and the&nbsp;<\/em>means \u201czero or more times\u201d. So, .* matches any sequence of characters (including no characters at all). : This matches one or more digits. The s a shorthand character class that matches any digit, and the + means \u201cone or more times\u201d. .<em>: This matches any character zero or more times, just like the previous .<\/em>. Lyrics: This matches the literal string \u201cLyrics\u201d followed by a newline character. So, the regular expression as a whole matches any line that begins with any sequence of characters, followed by one or more digits, followed by any sequence of characters, followed by the string \u201cLyrics\u201d and a newline character. This pattern matches lines like:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\n12&nbsp;ContributorsOne <strong>of<\/strong>&nbsp;Them Girls Lyrics\n7&nbsp;ContributorsBoyfriend (<strong>with<\/strong>&nbsp;Social House) Lyrics\n2&nbsp;ContributorsDon't Start Now Lyrics<\/code><\/pre>\n\n\n\n<p>By using this regular expression to remove the text before the line that includes a number and \u201cLyrics\u201d, we can extract only the lyrics themselves from the Genius.com webpage.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Contributed by Montaque Reynolds, Saint Louis University I wondered if I could useChatGPT to develop a webscraper for genius.com that [&hellip;]<\/p>\n","protected":false},"author":160,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_sb_is_suggestion_mode":false,"_sb_show_suggestion_boards":false,"_sb_show_comment_boards":false,"_sb_suggestion_history":"","_sb_update_block_changes":"","footnotes":""},"categories":[10,1],"tags":[19,39,38],"class_list":["post-311","post","type-post","status-publish","format-standard","hentry","category-tutorials","category-uncategorized","tag-ai","tag-walkthrough","tag-webscraping"],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/iris.siue.edu\/stldigitalhumanities\/wp-json\/wp\/v2\/posts\/311","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/iris.siue.edu\/stldigitalhumanities\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/iris.siue.edu\/stldigitalhumanities\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/iris.siue.edu\/stldigitalhumanities\/wp-json\/wp\/v2\/users\/160"}],"replies":[{"embeddable":true,"href":"https:\/\/iris.siue.edu\/stldigitalhumanities\/wp-json\/wp\/v2\/comments?post=311"}],"version-history":[{"count":3,"href":"https:\/\/iris.siue.edu\/stldigitalhumanities\/wp-json\/wp\/v2\/posts\/311\/revisions"}],"predecessor-version":[{"id":314,"href":"https:\/\/iris.siue.edu\/stldigitalhumanities\/wp-json\/wp\/v2\/posts\/311\/revisions\/314"}],"wp:attachment":[{"href":"https:\/\/iris.siue.edu\/stldigitalhumanities\/wp-json\/wp\/v2\/media?parent=311"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/iris.siue.edu\/stldigitalhumanities\/wp-json\/wp\/v2\/categories?post=311"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/iris.siue.edu\/stldigitalhumanities\/wp-json\/wp\/v2\/tags?post=311"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}