- Краткое руководство по библиотеке Python Requests
- Создание GET и POST запроса
- Передача параметров в URL
- Содержимое ответа (response)
- Бинарное содержимое ответа
- Содержимое ответа в JSON
- Необработанное содержимое ответа
- How to check if URLs are redirected using Requests
- Learn how to use the Python Requests library to check the status code of a URL and identify whether it's being redirected to a different URL.
- What is a site migration?
- Why detect redirects during a site migration?
- Load the packages
- Load the data
- Loop over the URLs and check for redirects
- Check your sitemap URLs for redirects
Краткое руководство по библиотеке Python Requests
Прежде чем начать, убедитесь, что установлена последняя версия Requests.
Для начала, давайте рассмотрим простые примеры.
Создание GET и POST запроса
Импортируйте модуль Requests:
Попробуем получить веб-страницу с помощью get-запроса. В этом примере давайте рассмотрим общий тайм-лайн GitHub:
r = requests.get('https://api.github.com/events')Мы получили объект Response с именем r . С помощью этого объекта можно получить всю необходимую информацию.
Простой API Requests означает, что все типы HTTP запросов очевидны. Ниже приведен пример того, как вы можете сделать POST запрос:
r = requests.post('https://httpbin.org/post', data = )Другие типы HTTP запросов, такие как : PUT, DELETE, HEAD и OPTIONS так же очень легко выполнить:
r = requests.put('https://httpbin.org/put', data = ) r = requests.delete('https://httpbin.org/delete') r = requests.head('https://httpbin.org/get') r = requests.options('https://httpbin.org/get')Передача параметров в URL
Часто вам может понадобится отправить какие-то данные в строке запроса URL. Если вы настраиваете URL вручную, эти данные будут представлены в нем в виде пар ключ/значение после знака вопроса. Например, httpbin.org/get?key=val . Requests позволяет передать эти аргументы в качестве словаря, используя аргумент params . Если вы хотите передать key1=value1 и key2=value2 ресурсу httpbin.org/get , вы должны использовать следующий код:
payload = r = requests.get('https://httpbin.org/get', params=payload) print(r.url)Как видно, URL был сформирован правильно:
https://httpbin.org/get?key2=value2&key1=value1
Ключ словаря, значение которого None , не будет добавлен в строке запроса URL.
Вы можете передать список параметров в качестве значения:
>>> payload = >>> r = requests.get('https://httpbin.org/get', params=payload) >>> print(r.url) https://httpbin.org/get?key1=value1&key2=value2&key2=value3Содержимое ответа (response)
Мы можем прочитать содержимое ответа сервера. Рассмотрим снова тайм-лайн GitHub:
>>> import requests >>> r = requests.get('https://api.github.com/events') >>> r.text '[Requests будет автоматически декодировать содержимое ответа сервера. Большинство кодировок unicode декодируются без проблем.
Когда вы делаете запрос, Requests делает предположение о кодировке, основанное на заголовках HTTP. Эта же кодировка текста, используется при обращение к r.text . Можно узнать, какую кодировку использует Requests, и изменить её с помощью r.encoding :>>> r.encoding 'utf-8' >>> r.encoding = 'ISO-8859-1'Если вы измените кодировку, Requests будет использовать новое значение r.encoding всякий раз, когда вы будете использовать r.text . Вы можете сделать это в любой ситуации, где нужна более специализированная логика работы с кодировкой содержимого ответа.
Например, в HTML и XML есть возможность задавать кодировку прямо в теле документа. В подобных ситуациях вы должны использовать r.content , чтобы найти кодировку, а затем установить r.encoding . Это позволит вам использовать r.text с правильной кодировкой.
Requests может также использовать пользовательские кодировки в случае, если в них есть потребность. Если вы создали свою собственную кодировку и зарегистрировали ее в модуле codecs, используйте имя кодека в качестве значения r.encoding .
Бинарное содержимое ответа
Вы можете также получить доступ к телу ответа в виде байтов для не текстовых ответов:
Передача со сжатием gzip и deflate автоматически декодируются для вас.
Например, чтобы создать изображение на основе бинарных данных, возвращаемых при ответе на запрос, используйте следующий код:
from PIL import Image from io import BytesIO i = Image.open(BytesIO(r.content))Содержимое ответа в JSON
Если вы работаете с данными в формате JSON, воспользуйтесь встроенным JSON декодером:
>>> import requests >>> r = requests.get('https://api.github.com/events') >>> r.json() [Если декодирование в JSON не удалось, r.json() вернет исключение. Например, если ответ с кодом 204 (No Content), или на случай если ответ содержит не валидный JSON, попытка обращения к r.json() будет возвращать ValueError: No JSON object could be decoded .
Следует отметить, что успешный вызов r.json() не указывает на успешный ответ сервера. Некоторые серверы могут возвращать объект JSON при неудачном ответе (например, сведения об ошибке HTTP 500). Такой JSON будет декодирован и возвращен. Для того, чтобы проверить успешен ли запрос, используйте r.raise_for_status() или проверьте какой r.status_code .
Необработанное содержимое ответа
В тех редких случаях, когда вы хотите получить доступ к “сырому” ответу сервера на уровне сокета, обратитесь к r.raw . Если вы хотите сделать это, убедитесь, что вы указали stream=True в вашем первом запросе. После этого вы уже можете проделать следующее:
How to check if URLs are redirected using Requests
Learn how to use the Python Requests library to check the status code of a URL and identify whether it's being redirected to a different URL.
The requests HTTP library for Python allows you to make HTTP requests to servers and receive back HTTP status codes, site content, and other data. It’s extremely useful for building web scraping projects and is one of the most widely used Python SEO tools.
One particularly useful feature of requests for those who work in SEO, or support an SEO team using their data science skills, is that the package can return HTTP status codes and redirect information for URLs. This can be extremely useful during SEO site migrations.
What is a site migration?
A site migration is the technical name SEOs use to refer to the re-mapping of URLs from an old site to a new one, or an old domain to a new one. During an SEO site migration your SEO team will identify all the URLs from your old site and those from your old site and then create a URL redirection plan so that anyone visiting an old URL is redirected to a new one, without hitting a 404.
The dataset of URLs from the old site are harvested from a range of data sources, including site crawls, Google Analytics, Google Search Console, and SEO tools such as Ahrefs, and will include not only the current URLs on the site, present in the sitemap and crawl data, but also those URLs that have appeared in the various systems over time.
Once the two datasets have been created, fuzzy matching (usually via fuzzywuzzy , or more recently polyfuzz ) can be applied to find the closest matching URL on the new site to the one on the old site. This means that anyone who lands on an old URL for, say, /how-to-keep-a-hamster will be redirected to the closest matching URL on the new site, even if it’s slightly different, i.e. /everything-you-need-to-know-to-keep-a-hamster .
Why detect redirects during a site migration?
If you simply generate a list of all the old URLs and map each one to the closest URL on the new site you’ll potentially be ignoring the existing redirects that site administrators may have put in place. For example, if the product at /super-widget-x1000 has been discontinued, your site admins might have replaced it with mega-tool-x2000 and created a redirect. However, fuzzy matching would ignore this and send the user somewhere potentially less relevant.
This can result in you redirecting traffic to another page using fuzzy matching and ignoring a human-selected alternative. Next, I’ll show you how you can use Requests to crawl a list of URLs and identify if they are redirected, and to where. This can give you extra data to ensure more accurate redirections during your site migration.
Load the packages
First, open a Jupyter notebook and import the requests and pandas packages. We’ll use Pandas to load and manipulate the data on the URLs and create an output dataframe that we can save to CSV, and we’ll use requests for checking each URL.
import requests import pandas as pd
Load the data
Next, load up the list of URLs you want to check. I’ve included a simple list below, but you’ll probably have yours in a CSV file. If that’s the case, you can extract the column and save it to a list using code like this: urls = df['url'].tolist() . That will take the url column in your dataframe and return a list of values to check.
urls = [ 'https://bbc.co.uk/iplayer', 'https://facebook.com/', 'http://www.theguardian.co.uk', 'https://practicaldatascience.co.uk' ]
Loop over the URLs and check for redirects
Now we have our list of URLs to check, we’ll create a for loop to check each one using requests . Before doing this, we’ll create an empty Pandas dataframe called df_output into which we’ll store the original URL and its HTTP status code (i.e. 200 for OK, 301 for a permanent redirect, 302 for a temporary redirect, or 404 for page not found), then we’ll record the destination URL and destination HTTP status code if a redirect was detected.
We’ll pass each URL to requests and make a GET request, passing in a user agent to help ensure the server returns a response (some servers won’t return one if you don’t provide a user agent string). Then we’ll create an empty dictionary and capture the values.
If the response object from requests contains a value in history that means we have a redirect, so we can fetch the url and status_code and store them. If there’s no history , then no redirect was found and we can just store the original URL and status code and some blank values.
df_output = pd.DataFrame(columns=['original_url', 'original_status', 'destination_url', 'destination_status']) for url in urls: response = requests.get(url, headers='User-Agent': 'Google Chrome'>) row = <> if response.history: for step in response.history: row['original_url'] = step.url row['original_status'] = step.status_code row['destination_url'] = response.url row['destination_status'] = response.status_code else: row['original_url'] = response.url row['original_status'] = response.status_code row['destination_url'] = '' row['destination_status'] = '' print(row) df_output = df_output.append(row, ignore_index=True)
I’ve printed out each row dictionary so I can monitor progress, then I’ve used the Pandas append() to add each row to the dataframe. Finally, we can print the df_output dataframe to see the HTTP status code and redirect for each URL in our list.
original_url | original_status | destination_url | destination_status | |
---|---|---|---|---|
0 | https://bbc.co.uk/iplayer | 301 | https://www.bbc.co.uk/iplayer | 200 |
1 | https://facebook.com/ | 301 | https://www.facebook.com/ | 200 |
2 | https://www.theguardian.com/ | 302 | https://www.theguardian.com/uk | 200 |
3 | https://practicaldatascience.co.uk/ | 200 |
Check your sitemap URLs for redirects
Another useful application of this technique is to check your sitemap URLs for redirects. You’d typically expect any of the pages listed in your XML sitemap to not redirect to another page, otherwise users will never be able to reach desired page.
The easiest way to do this is via my EcommerceTools package, which you can install by entering the following command in your terminal: !pip3 install --upgrade ecommercetools .
By running the seo.get_sitemap() function and passing in the URL of your XML sitemap you can create a Pandas dataframe containing all your site URLs and then check whether they redirect. If they do, you need to remove the redirects so the pages can be reached.
import requests import pandas as pd from ecommercetools import seo df = seo.get_sitemap('https://www.examplecom/sitemap.xml') urls = df['loc'].tolist() df_output = pd.DataFrame(columns=['original_url', 'original_status', 'destination_url', 'destination_status']) for url in urls: response = requests.get(url, headers='User-Agent': 'Google Chrome'>) row = <> if response.history: for step in response.history: row['original_url'] = step.url row['original_status'] = step.status_code row['destination_url'] = response.url row['destination_status'] = response.status_code else: row['original_url'] = response.url row['original_status'] = response.status_code row['destination_url'] = '' row['destination_status'] = '' print(row) df_output = df_output.append(row, ignore_index=True) df_output
Matt Clarke, Wednesday, February 02, 2022