I am very new to Android Kotlin programming. I am making an app to create, read and delete file using Storage Access Framework. I did it by implementing deprecated startActivityForResult intent to perform file read, create, delete tasks. I tried to implement it using Activity Result API but I got stuck in request code which I could not find it.
In new implementation, there is resultCode but no requestCode.
My implemetation is below. How I can I implement the following using Activity Result API ?
How can I get request code from Activity Result API ?
fun createFile()
{
val filename: String = etFileName.text.toString()
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
type = "text/*"
addCategory(Intent.CATEGORY_OPENABLE)
putExtra(Intent.EXTRA_TITLE, filename)
}
startActivityForResult(intent, WRITE_REQUEST_CODE)
}
fun readFile(){
etFileName.setText("")
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "text/*"
}
startActivityForResult(intent, READ_REQUEST_CODE)
}
fun deleteFile(uri: Uri){
val filename = queryName(contentResolver, uri)
DocumentsContract.deleteDocument(contentResolver, uri)
Toast.makeText(applicationContext, "Done deleting $filename", Toast.LENGTH_SHORT).show()
}
fun writeText(uri: Uri) : String{
//var writetext: String = "typing high speed"
var writeStream = contentResolver.openFileDescriptor(uri, "w")
val filename: String = queryName(contentResolver, uri)
etFileName.setText(filename)
var fileOutputStream = FileOutputStream(writeStream?.fileDescriptor)
fileOutputStream.write(filename.toByteArray())
fileOutputStream.close()
return filename.toString()
}
fun openFileContent(uri: Uri): String{
val inputStream = contentResolver.openInputStream(uri)
val reader = BufferedReader(InputStreamReader(inputStream))
val stringBuilder = StringBuilder()
val filename = queryName(contentResolver, uri)
etFileName.setText(filename)
var currentline = reader.readLine()
while (currentline != null) {
stringBuilder.append(currentline + "n")
currentline = reader.readLine()
}
inputStream?.close()
val str = stringBuilder.toString()
Log.d("Uri Read", ": $str")
return str
}
private fun queryName(resolver: ContentResolver, uri: Uri): String {
val returnCursor: Cursor = resolver.query(uri, null, null, null, null)!!
val nameIndex: Int = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
returnCursor.moveToFirst()
val name: String = returnCursor.getString(nameIndex)
returnCursor.close()
return name
}
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
super.onActivityResult(requestCode, resultCode, resultData)
if (requestCode == READ_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
val uri =resultData?.data
Log.d("Uri Read", "$uri")
if (uri != null) {
val readfile: String = openFileContent(uri)
etContent.setText(readfile)
}
} else if (requestCode == WRITE_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
resultData?.data?.also { uri ->
Log.i("Uri Write", "Uri: $uri") // 1
val write = writeText(uri) // 2
etContent.setText(write)
}
} else if (requestCode == DELETE_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
val uri =resultData?.data
Log.d("Uri Delete", "$uri")
if (uri != null) {
deleteFile(uri)
}
}
}
Since the above method is deprecated, I tried to implement it using Intent launcher, but there is no reference to requestCode anywhere so I am stuck here. It is as shown below :
val startforFile: ActivityResultLauncher<Intent> = registerForActivityResult(ActivityResultContracts.StartActivityForResult()){
result: ActivityResult ->
// could not find reference to requestCode here
if (requestCode == READ_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
val uri =resultData?.data
Log.d("Uri Read", "$uri")
if (uri != null) {
val readfile: String = openFileContent(uri)
etContent.setText(readfile)
}
} else if (requestCode == WRITE_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
resultData?.data?.also { uri ->
Log.i("Uri Write", "Uri: $uri") // 1
val write = writeText(uri) // 2
etContent.setText(write)
}
} else if (requestCode == DELETE_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
val uri =resultData?.data
Log.d("Uri Delete", "$uri")
if (uri != null) {
deleteFile(uri)
}
}
}
Can anyone show me how it is done correctly ?
В этом уроке:
— разбираемся, зачем нужны requestCode и resultCode в onActivityResult
На прошлом уроке мы поверхностно рассмотрели, как вызвать Activity, и как сделать так, чтобы она вернула результат. Рассмотрим немного подробней этот механизм. Создадим приложение, которое будет вызывать два разных Activity и получать от них результат. Как мы помним, результат приходит в метод onActivityResult. И requestCode используется, чтобы отличать друг от друга пришедшие результаты. А resultCode – позволяет определить успешно прошел вызов или нет.
Создадим проект:
Project name: P0301_ActivityResult
Build Target: Android 2.3.3
Application name: ActivityResult
Package name: ru.startandroid.develop.p0301activityresult
Create Activity: MainActivity
Нарисуем экран в main.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <TextView android:id="@+id/tvText" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:gravity="center_horizontal" android:text="Hello World" android:textSize="20sp"> </TextView> <LinearLayout android:id="@+id/linearLayout1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="20dp" android:orientation="horizontal"> <Button android:id="@+id/btnColor" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginRight="5dp" android:layout_weight="1" android:text="Color"> </Button> <Button android:id="@+id/btnAlign" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:layout_weight="1" android:text="Alignment"> </Button> </LinearLayout> </LinearLayout>
На экране TextView с текстом. И две кнопки для выбора цвета шрифта и выравнивания текста в TextView. Нажатие на кнопку будет вызывать Activity для выбора и получать обратно результат.
Давайте начнем кодить в MainActivity.java:
package ru.startandroid.develop.p0301activityresult; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class MainActivity extends Activity implements OnClickListener { TextView tvText; Button btnColor; Button btnAlign; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); tvText = (TextView) findViewById(R.id.tvText); btnColor = (Button) findViewById(R.id.btnColor); btnAlign = (Button) findViewById(R.id.btnAlign); btnColor.setOnClickListener(this); btnAlign.setOnClickListener(this); } @Override public void onClick(View v) { // TODO Auto-generated method stub } }
Определили экранные элементы, прописали обработчик кнопкам и пока остановимся на этом.
Создадим два других Activity. Начнем с Activity для выбора цвета. Создадим layout-файл color.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <Button android:id="@+id/btnRed" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="5dp" android:layout_weight="1" android:text="Red"> </Button> <Button android:id="@+id/btnGreen" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="5dp" android:layout_weight="1" android:text="Green"> </Button> <Button android:id="@+id/btnBlue" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="5dp" android:layout_weight="1" android:text="Blue"> </Button> </LinearLayout>
Создаем класс ColorActivity. ColorActivity.java:
package ru.startandroid.develop.p0301activityresult; import android.app.Activity; import android.content.Intent; import android.graphics.Color; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class ColorActivity extends Activity implements OnClickListener { Button btnRed; Button btnGreen; Button btnBlue; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.color); btnRed = (Button) findViewById(R.id.btnRed); btnGreen = (Button) findViewById(R.id.btnGreen); btnBlue = (Button) findViewById(R.id.btnBlue); btnRed.setOnClickListener(this); btnGreen.setOnClickListener(this); btnBlue.setOnClickListener(this); } @Override public void onClick(View v) { Intent intent = new Intent(); switch (v.getId()) { case R.id.btnRed: intent.putExtra("color", Color.RED); break; case R.id.btnGreen: intent.putExtra("color", Color.GREEN); break; case R.id.btnBlue: intent.putExtra("color", Color.BLUE); break; } setResult(RESULT_OK, intent); finish(); } }
Как обычно определяем элементы, присваиваем обработчик кнопкам и реализуем onClick. В onClick мы создаем Intent, затем определяем, кнопка с каким цветом была нажата и помещаем в Intent объект с именем color и значением цвета. Ставим статус RESULT_OK, указываем, что надо вернуть объект intent в качестве результата и закрываем Activity. Для значения цветов используем системные константы.
Аналогично создаем Activity для выбора выравнивания.
Layout-файл align.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <Button android:id="@+id/btnLeft" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="5dp" android:layout_weight="1" android:text="Left"> </Button> <Button android:id="@+id/btnCenter" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="5dp" android:layout_weight="1" android:text="Center"> </Button> <Button android:id="@+id/btnRight" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="5dp" android:layout_weight="1" android:text="Right"> </Button> </LinearLayout>
AlignActivity.java:
package ru.startandroid.develop.p0301activityresult; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.Gravity; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class AlignActivity extends Activity implements OnClickListener { Button btnLeft; Button btnCenter; Button btnRight; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.align); btnLeft = (Button) findViewById(R.id.btnLeft); btnCenter = (Button) findViewById(R.id.btnCenter); btnRight = (Button) findViewById(R.id.btnRight); btnLeft.setOnClickListener(this); btnCenter.setOnClickListener(this); btnRight.setOnClickListener(this); } @Override public void onClick(View v) { Intent intent = new Intent(); switch (v.getId()) { case R.id.btnLeft: intent.putExtra("alignment", Gravity.LEFT); break; case R.id.btnCenter: intent.putExtra("alignment", Gravity.CENTER); break; case R.id.btnRight: intent.putExtra("alignment", Gravity.RIGHT); break; } setResult(RESULT_OK, intent); finish(); } }
Здесь все аналогично, как и в ColorActivity. Только работаем не с цветами, а с выравниванием. Не забудьте прописать оба Activity в манифесте.
Теперь можем завершить код в MainActivity.java. Добавим пару своих констант в класс для удобства:
final int REQUEST_CODE_COLOR = 1; final int REQUEST_CODE_ALIGN = 2;
Эти константы далее будем использовать в качестве requestCode.
Допишем метод onClick:
@Override public void onClick(View v) { Intent intent; switch (v.getId()) { case R.id.btnColor: intent = new Intent(this, ColorActivity.class); startActivityForResult(intent, REQUEST_CODE_COLOR); break; case R.id.btnAlign: intent = new Intent(this, AlignActivity.class); startActivityForResult(intent, REQUEST_CODE_ALIGN); break; } }
Мы определяем, какая кнопка была нажата и посылаем Intent с ожиданием возврата результата. Два вызова отличаются классом вызываемого Activity и параметром requestCode в методе startActivityForResult. При вызове ColorActivity используем константу REQUEST_CODE_COLOR, а при вызове AlignActivity — REQUEST_CODE_ALIGN. Эту константу мы обратно получим в методе обработки результата – onActivityResult, и по ней сможем определить из какого именно Activity пришел результат.
Давайте реализуем метод onActivityResult в MainActivity.java:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // запишем в лог значения requestCode и resultCode Log.d("myLogs", "requestCode = " + requestCode + ", resultCode = " + resultCode); // если пришло ОК if (resultCode == RESULT_OK) { switch (requestCode) { case REQUEST_CODE_COLOR: int color = data.getIntExtra("color", Color.WHITE); tvText.setTextColor(color); break; case REQUEST_CODE_ALIGN: int align = data.getIntExtra("alignment", Gravity.LEFT); tvText.setGravity(align); break; } // если вернулось не ОК } else { Toast.makeText(this, "Wrong result", Toast.LENGTH_SHORT).show(); } }
Для наглядности пишем в лог значения переменных.
Вспоминаем, что в ColorActivity и AlignActivity в методе setResult мы ставили статус RESULT_OK при отправке результата. Значит в onActivityResult нам надо ожидать этот статус, как обозначение успешного окончания вызова.
Если вызов прошел успешно (resultCode = RESULT_OK), то мы смотрим значение requestCode. Если оно равно константе REQUEST_CODE_COLOR, то вспоминаем, что мы использовали эту константу в методе startActivityForResult, когда отправляли запрос на выбор цвета. Значит, нам пришел результат этого выбора. Мы берем Intent (data) и извлекаем из него значение объекта с именем color и присваиваем это значение цвету текста в TextView. Константа Color.WHITE в методе getIntExtra означает значение по умолчанию. Т.е. если в Intent не найдется объекта с именем color, то метод вернет белый (white) цвет.
Аналогично для REQUEST_CODE_ALIGN. Эту константу мы использовали для запроса выбора выравнивания. И если в методе onActivityResult параметр requestCode = этой константе, значит пришел ответ на запрос выравнивания. И мы считываем это значение из Intent и присваиваем его атрибуту Gravity для TextView.
Если resultCode не равен RESULT_OK, значит что-то пошло не так. Выводим на экран соответствующее сообщение. Этот случай может наступить, например, если на экране выбора не делать выбор, а нажать кнопку Назад.
Давайте все сохраним и запустим приложение.
Нажмем Color
и выберем, например Red
Цвет изменился
смотрим лог:
requestCode = 1, resultCode = -1
requestCode пришедший в метод onActivityResult равен 1. Все верно, это значение константы REQUEST_CODE_COLOR, которое мы использовали при вызове.
resultCode = -1 – это значение системной константы RESULT_OK
Т.е. все верно, пришел ответ на запрос цвета, и его статус = RESULT_OK.
Теперь жмем Alignment и выбираем Right, получаем выравнивание вправо:
Смотрим лог:
requestCode = 2, resultCode = -1
requestCode = 2, что равно константе REQUEST_CODE_ALIGN. Значит пришел ответ на запрос выравнивания.
resultCode = -1, т.е. RESULT_OK.
Теперь снова жмем Color
но вместо того, чтобы выбрать цвет нажмем кнопку назад
Отобразилось наше сообщение об ошибке. Смотрим логи:
requestCode = 1, resultCode = 0
requestCode = 1 – все верно, мы запрашивали цвет (REQUEST_CODE_COLOR)
resultCode = 0, это значение константы RESULT_CANCELED, значит вызов прошел неудачно
Ограничений на значение статуса в методе setResult нет. RESULT_OK и RESULT_CANCELED – системные общепринятые константы. Но вы можете свободно использовать свои значения, если в этом есть необходимость.
Итак, подведем итог.
requestCode – это в некотором роде ID запроса. Задается в методе startActivityForResult, и проверяется потом в onActivityResult, чтобы точно знать, на какой вызов пришел ответ.
resultCode – статус вызова. Задается в методе setResult, и проверяется в onActivityResult, чтобы понять насколько успешно прошел вызов. Если при вызове что-то пошло не так, то вернется системная константа RESULT_CANCELED.
Полный код MainActivity.java:
package ru.startandroid.develop.p0301activityresult; import android.app.Activity; import android.content.Intent; import android.graphics.Color; import android.os.Bundle; import android.util.Log; import android.view.Gravity; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity implements OnClickListener { final int REQUEST_CODE_COLOR = 1; final int REQUEST_CODE_ALIGN = 2; TextView tvText; Button btnColor; Button btnAlign; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); tvText = (TextView) findViewById(R.id.tvText); btnColor = (Button) findViewById(R.id.btnColor); btnAlign = (Button) findViewById(R.id.btnAlign); btnColor.setOnClickListener(this); btnAlign.setOnClickListener(this); } @Override public void onClick(View v) { Intent intent; switch (v.getId()) { case R.id.btnColor: intent = new Intent(this, ColorActivity.class); startActivityForResult(intent, REQUEST_CODE_COLOR); break; case R.id.btnAlign: intent = new Intent(this, AlignActivity.class); startActivityForResult(intent, REQUEST_CODE_ALIGN); break; } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // запишем в лог значения requestCode и resultCode Log.d("myLogs", "requestCode = " + requestCode + ", resultCode = " + resultCode); // если пришло ОК if (resultCode == RESULT_OK) { switch (requestCode) { case REQUEST_CODE_COLOR: int color = data.getIntExtra("color", Color.WHITE); tvText.setTextColor(color); break; case REQUEST_CODE_ALIGN: int align = data.getIntExtra("alignment", Gravity.LEFT); tvText.setGravity(align); break; } // если вернулось не ОК } else { Toast.makeText(this, "Wrong result", Toast.LENGTH_SHORT).show(); } } }
На следующем уроке:
— узнаем что такое URI
— вызываем системные приложения (браузер, звонилка, карта)
Присоединяйтесь к нам в Telegram:
— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Compose, Kotlin, RxJava, Dagger, Тестирование, Performance
— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
Продолжаем изучать обмен данными между экранами android приложения. В этом уроке создаем android приложение, которое будет вызывать два разных Activity и получать от них данные. Как мы помним, результат приходит в метод onActivityResult. И requestCode используется, чтобы отличать друг от друга пришедшие результаты. А resultCode – позволяет определить, успешно прошел вызов или нет.
Исходный код классов из урока – под видео:
[pastacode lang=”css” message=”activity_main.xml” highlight=”” provider=”manual”]
[/pastacode]
[pastacode lang=”java” message=”MainActivity.java” highlight=”” provider=”manual”]
package info.fandroid.activityresult;
import android.content.Intent;
import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
final int REQUEST_CODE_COLOR = 1;
final int REQUEST_CODE_ALIGN = 2;
TextView tvText;
Button btnColor;
Button btnAlign;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvText = (TextView)findViewById(R.id.tvText);
btnColor = (Button)findViewById(R.id.btnColor);
btnAlign = (Button)findViewById(R.id.btnAlign);
btnAlign.setOnClickListener(this);
btnColor.setOnClickListener(this);
}
@Override
public void onClick(View v) {
Intent intent;
switch (v.getId()){
case R.id.btnColor:
intent = new Intent(this, ColorActivity.class);
startActivityForResult(intent, REQUEST_CODE_COLOR);
break;
case R.id.btnAlign:
intent = new Intent(this, AlignActivity.class);
startActivityForResult(intent, REQUEST_CODE_ALIGN);
break;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d("myLogs", "requestCode = " + requestCode + ", resultCode = " + resultCode);
if (resultCode == RESULT_OK){
switch (requestCode){
case REQUEST_CODE_COLOR:
int color = data.getIntExtra("color", Color.WHITE);
tvText.setTextColor(color);
break;
case REQUEST_CODE_ALIGN:
int align = data.getIntExtra("alignment", Gravity.LEFT);
tvText.setGravity(align);
break;
}
} else {
Toast.makeText(MainActivity.this, "Wrong result", Toast.LENGTH_SHORT).show();
}
}
}
[/pastacode]
[pastacode lang=”css” message=”activity_color.xml” highlight=”” provider=”manual”]
[/pastacode]
[pastacode lang=”java” message=”ColorActivity.java” highlight=”” provider=”manual”]
package info.fandroid.activityresult;
import android.content.Intent;
import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class ColorActivity extends AppCompatActivity implements View.OnClickListener{
Button btnRed;
Button btnGreen;
Button btnBlue;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_color);
btnRed = (Button)findViewById(R.id.btnRed);
btnGreen = (Button)findViewById(R.id.btnGreen);
btnBlue = (Button)findViewById(R.id.btnBlue);
btnRed.setOnClickListener(this);
btnGreen.setOnClickListener(this);
btnBlue.setOnClickListener(this);
}
@Override
public void onClick(View v) {
Intent intent = new Intent();
switch (v.getId()){
case R.id.btnRed:
intent.putExtra("color", Color.RED);
break;
case R.id.btnGreen:
intent.putExtra("color", Color.GREEN);
break;
case R.id.btnBlue:
intent.putExtra("color", Color.BLUE);
break;
}
setResult(RESULT_OK, intent);
finish();
}
}
[/pastacode]
[pastacode lang=”css” message=”activity_align.xml” highlight=”” provider=”manual”]
[/pastacode]
[pastacode lang=”java” message=”AlignActivity.java” highlight=”” provider=”manual”]
package info.fandroid.activityresult;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.widget.Button;
public class AlignActivity extends AppCompatActivity implements View.OnClickListener{
Button btnLeft;
Button btnCenter;
Button btnRight;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_align);
btnLeft = (Button)findViewById(R.id.btnLeft);
btnCenter = (Button)findViewById(R.id.btnCenter);
btnRight = (Button)findViewById(R.id.btnRight);
btnLeft.setOnClickListener(this);
btnCenter.setOnClickListener(this);
btnRight.setOnClickListener(this);
}
@Override
public void onClick(View v) {
Intent intent = new Intent();
switch (v.getId()){
case R.id.btnLeft:
intent.putExtra("alignment", Gravity.LEFT);
break;
case R.id.btnCenter:
intent.putExtra("alignment", Gravity.CENTER);
break;
case R.id.btnRight:
intent.putExtra("alignment", Gravity.RIGHT);
break;
}
setResult(RESULT_OK, intent);
finish();
}
}
[/pastacode]
Больше уроков:
Инструменты android разработчика: тут
Дизайн android приложений: тут
Уроки создания игр для android: тут
Основы программирования на JAVA: тут
<<Урок 29. Вызов второго Activity с возвращением данных | Уроки Android Studio
Урок 31. Вызываем браузер, звонилку, карты с помощью intent с атрибутом data — Uri >>
Библиотека requests
является стандартным инструментом для составления HTTP-запросов в Python. Простой и аккуратный API значительно облегчает трудоемкий процесс создания запросов. Таким образом, можно сосредоточиться на взаимодействии со службами и использовании данных в приложении.
Содержание статьи
- Python установка библиотеки requests
- Python библиотека Requests метод GET
- Объект Response получение ответа на запрос в Python
- HTTP коды состояний
- Получить содержимое страницы в Requests
- HTTP заголовки в Requests
- Python Requests параметры запроса
- Настройка HTTP заголовка запроса (headers)
- Примеры HTTP методов в Requests
- Python Requests тело сообщения
- Python Requests анализ запроса
- Python Requests аутентификация HTTP AUTH
- Python Requests проверка SSL сертификата
- Python Requests производительность приложений
- Объект Session в Requests
- HTTPAdapter — Максимальное количество повторов запроса в Requests
В данной статье представлены наиболее полезные особенности requests. Показано, как изменить и приспособить requests к различным ситуациям, с которыми программисты сталкиваются чаще всего. Здесь также даются советы по эффективному использованию requests и предотвращению влияния сторонних служб, которые могут сильно замедлить работу используемого приложения. Мы использовали библиотек requests в уроке по парсингу html через библиотеку BeautifulSoup.
Ключевые аспекты инструкции:
- Создание запросов при помощи самых популярных HTTP методов;
- Редактирование заголовков запросов и данных при помощи строки запроса и содержимого сообщения;
- Анализ данных запросов и откликов;
- Создание авторизированных запросов;
- Настройка запросов для предотвращения сбоев и замедления работы приложения.
В статье собран оптимальный набор информации, необходимый для понимания данных примеров и особенностей их использования. Информация представлена в доступной в форме. Тем не менее, стоит иметь в виду, что для оптимального разбора инструкции потребуются хотя бы базовые знания HTTP.
Далее будут показаны наиболее эффективные методы использования requests
в разрабатываемом приложении.
Python установка библиотеки requests
Для начала работы потребуется установить библиотеку requests
. Для этого используется следующая команда.
Есть вопросы по Python?
На нашем форуме вы можете задать любой вопрос и получить ответ от всего нашего сообщества!
Telegram Чат & Канал
Вступите в наш дружный чат по Python и начните общение с единомышленниками! Станьте частью большого сообщества!
Паблик VK
Одно из самых больших сообществ по Python в социальной сети ВК. Видео уроки и книги для вас!
Тем, кто для работы с пакетами Python, использует виртуальную среду Pipenv, необходимо использовать немного другую команду.
$ pipenv install requests |
Сразу после установки requests
можно полноценно использовать в приложении. Импорт requests
производится следующим образом.
Таким образом, все подготовительные этапы для последующего использования requests
завершены. Начинать изучение requests лучше всего с того, как сделать запрос GET
.
Python библиотека Requests метод GET
Такие HTTP методы, как GET
и POST
, определяют, какие действия будут выполнены при создании HTTP запроса. Помимо GET
и POST
для этой задачи могут быть использованы некоторые другие методы. Далее они также будут описаны в руководстве.
GET
является одним из самых популярных HTTP методов. Метод GET
указывает на то, что происходит попытка извлечь данные из определенного ресурса. Для того, чтобы выполнить запрос GET
, используется requests.get()
.
Для проверки работы команды будет выполнен запрос GET
в отношении Root REST API на GitHub. Для указанного ниже URL вызывается метод get()
.
requests.get(‘https://api.github.com’) <Response [200]> |
Если никакие python ошибки не возникло, вас можно поздравить – первый запрос успешно выполнен. Далее будет рассмотрен ответ на данный запрос, который можно получить при помощи объекта Response.
Объект Response получение ответа на запрос в Python
Response
представляет собой довольно мощный объект для анализа результатов запроса. В качестве примера будет использован предыдущий запрос, только на этот раз результат будет представлен в виде переменной. Таким образом, получится лучше изучить его атрибуты и особенности использования.
response = requests.get(‘https://api.github.com’) |
В данном примере при помощи get()
захватывается определенное значение, что является частью объекта Response
, и помещается в переменную под названием response
. Теперь можно использовать переменную response
для того, чтобы изучить данные, которые были получены в результате запроса GET
.
HTTP коды состояний
Самыми первыми данными, которые будут получены через Response
, будут коды состояния. Коды состояния сообщают о статусе запроса.
Например, статус 200 OK
значит, что запрос успешно выполнен. А вот статус 404 NOT FOUND
говорит о том, что запрашиваемый ресурс не был найден. Существует множество других статусных кодов, которые могут сообщить важную информацию, связанную с запросом.
Используя .status_code
, можно увидеть код состояния, который возвращается с сервера.
>>> response.status_code 200 |
.status_code
вернул значение 200
. Это значит, что запрос был выполнен успешно, а сервер ответил, отобразив запрашиваемую информацию.
В некоторых случаях необходимо использовать полученную информацию для написания программного кода.
if response.status_code == 200: print(‘Success!’) elif response.status_code == 404: print(‘Not Found.’) |
В таком случае, если с сервера будет получен код состояния 200
, тогда программа выведет значение Success!
. Однако, если от сервера поступит код 404
, тогда программа выведет значение Not Found
.
requests
может значительно упростить весь процесс. Если использовать Response
в условных конструкциях, то при получении кода состояния в промежутке от 200
до 400
, будет выведено значение True
. В противном случае отобразится значение False
.
Последний пример можно упростить при помощи использования оператора if
.
if response: print(‘Success!’) else: print(‘An error has occurred.’) |
Стоит иметь в виду, что данный способ не проверяет, имеет ли статусный код точное значение 200
. Причина заключается в том, что другие коды в промежутке от 200
до 400
, например, 204 NO CONTENT
и 304 NOT MODIFIED
, также считаются успешными в случае, если они могут предоставить действительный ответ.
К примеру, код состояния 204
говорит о том, что ответ успешно получен, однако в полученном объекте нет содержимого. Можно сказать, что для оптимально эффективного использования способа необходимо убедиться, что начальный запрос был успешно выполнен. Требуется изучить код состояния и в случае необходимости произвести необходимые поправки, которые будут зависеть от значения полученного кода.
Допустим, если при использовании оператора if
вы не хотите проверять код состояния, можно расширить диапазон исключений для неудачных результатов запроса. Это можно сделать при помощи использования .raise_for_status()
.
import requests from requests.exceptions import HTTPError for url in [‘https://api.github.com’, ‘https://api.github.com/invalid’]: try: response = requests.get(url) # если ответ успешен, исключения задействованы не будут response.raise_for_status() except HTTPError as http_err: print(f‘HTTP error occurred: {http_err}’) # Python 3.6 except Exception as err: print(f‘Other error occurred: {err}’) # Python 3.6 else: print(‘Success!’) |
В случае вызова исключений через .raise_for_status()
к некоторым кодам состояния применяется HTTPError
. Когда код состояния показывает, что запрос успешно выполнен, программа продолжает работу без применения политики исключений.
На заметку. Для более продуктивной работы в Python 3.6 будет не лишним изучить f-строки. Не стоит пренебрегать ими, так как это отличный способ упростить форматирование строк.
Анализ способов использования кодов состояния, полученных с сервера, является неплохим стартом для изучения requests. Тем не менее, при создании запроса GET, значение кода состояния является не самой важной информацией, которую хочет получить программист. Обычно запрос производится для извлечения более содержательной информации. В дальнейшем будет показано, как добраться до актуальных данных, которые сервер высылает отправителю в ответ на запрос.
Зачастую ответ на запрос GET
содержит весьма ценную информацию. Она находится в теле сообщения и называется пейлоад (payload). Используя атрибуты и методы библиотеки Response
, можно получить пейлоад в различных форматах.
Для того, чтобы получить содержимое запроса в байтах, необходимо использовать .content
.
>>> response = requests.get(‘https://api.github.com’) >>> response.content b‘{«current_user_url»:»https://api.github.com/user»,»current_user_authorizations_html_url»:»https://github.com/settings/connections/applications{/client_id}»,»authorizations_url»:»https://api.github.com/authorizations»,»code_search_url»:»https://api.github.com/search/code?q={query}{&page,per_page,sort,order}»,»commit_search_url»:»https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}»,»emails_url»:»https://api.github.com/user/emails»,»emojis_url»:»https://api.github.com/emojis»,»events_url»:»https://api.github.com/events»,»feeds_url»:»https://api.github.com/feeds»,»followers_url»:»https://api.github.com/user/followers»,»following_url»:»https://api.github.com/user/following{/target}»,»gists_url»:»https://api.github.com/gists{/gist_id}»,»hub_url»:»https://api.github.com/hub»,»issue_search_url»:»https://api.github.com/search/issues?q={query}{&page,per_page,sort,order}»,»issues_url»:»https://api.github.com/issues»,»keys_url»:»https://api.github.com/user/keys»,»notifications_url»:»https://api.github.com/notifications»,»organization_repositories_url»:»https://api.github.com/orgs/{org}/repos{?type,page,per_page,sort}»,»organization_url»:»https://api.github.com/orgs/{org}»,»public_gists_url»:»https://api.github.com/gists/public»,»rate_limit_url»:»https://api.github.com/rate_limit»,»repository_url»:»https://api.github.com/repos/{owner}/{repo}»,»repository_search_url»:»https://api.github.com/search/repositories?q={query}{&page,per_page,sort,order}»,»current_user_repositories_url»:»https://api.github.com/user/repos{?type,page,per_page,sort}»,»starred_url»:»https://api.github.com/user/starred{/owner}{/repo}»,»starred_gists_url»:»https://api.github.com/gists/starred»,»team_url»:»https://api.github.com/teams»,»user_url»:»https://api.github.com/users/{user}»,»user_organizations_url»:»https://api.github.com/user/orgs»,»user_repositories_url»:»https://api.github.com/users/{user}/repos{?type,page,per_page,sort}»,»user_search_url»:»https://api.github.com/search/users?q={query}{&page,per_page,sort,order}»}’ |
Использование .content
обеспечивает доступ к чистым байтам ответного пейлоада, то есть к любым данным в теле запроса. Однако, зачастую требуется конвертировать полученную информацию в строку в кодировке UTF-8. response
делает это при помощи .text
.
>>> response.text ‘{«current_user_url»:»https://api.github.com/user»,»current_user_authorizations_html_url»:»https://github.com/settings/connections/applications{/client_id}»,»authorizations_url»:»https://api.github.com/authorizations»,»code_search_url»:»https://api.github.com/search/code?q={query}{&page,per_page,sort,order}»,»commit_search_url»:»https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}»,»emails_url»:»https://api.github.com/user/emails»,»emojis_url»:»https://api.github.com/emojis»,»events_url»:»https://api.github.com/events»,»feeds_url»:»https://api.github.com/feeds»,»followers_url»:»https://api.github.com/user/followers»,»following_url»:»https://api.github.com/user/following{/target}»,»gists_url»:»https://api.github.com/gists{/gist_id}»,»hub_url»:»https://api.github.com/hub»,»issue_search_url»:»https://api.github.com/search/issues?q={query}{&page,per_page,sort,order}»,»issues_url»:»https://api.github.com/issues»,»keys_url»:»https://api.github.com/user/keys»,»notifications_url»:»https://api.github.com/notifications»,»organization_repositories_url»:»https://api.github.com/orgs/{org}/repos{?type,page,per_page,sort}»,»organization_url»:»https://api.github.com/orgs/{org}»,»public_gists_url»:»https://api.github.com/gists/public»,»rate_limit_url»:»https://api.github.com/rate_limit»,»repository_url»:»https://api.github.com/repos/{owner}/{repo}»,»repository_search_url»:»https://api.github.com/search/repositories?q={query}{&page,per_page,sort,order}»,»current_user_repositories_url»:»https://api.github.com/user/repos{?type,page,per_page,sort}»,»starred_url»:»https://api.github.com/user/starred{/owner}{/repo}»,»starred_gists_url»:»https://api.github.com/gists/starred»,»team_url»:»https://api.github.com/teams»,»user_url»:»https://api.github.com/users/{user}»,»user_organizations_url»:»https://api.github.com/user/orgs»,»user_repositories_url»:»https://api.github.com/users/{user}/repos{?type,page,per_page,sort}»,»user_search_url»:»https://api.github.com/search/users?q={query}{&page,per_page,sort,order}»}’ |
Декодирование байтов в строку требует наличия определенной модели кодировки. По умолчанию requests
попытается узнать текущую кодировку, ориентируясь по заголовкам HTTP. Указать необходимую кодировку можно при помощи добавления .encoding
перед .text
.
>>> response.encoding = ‘utf-8’ # Optional: requests infers this internally >>> response.text ‘{«current_user_url»:»https://api.github.com/user»,»current_user_authorizations_html_url»:»https://github.com/settings/connections/applications{/client_id}»,»authorizations_url»:»https://api.github.com/authorizations»,»code_search_url»:»https://api.github.com/search/code?q={query}{&page,per_page,sort,order}»,»commit_search_url»:»https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}»,»emails_url»:»https://api.github.com/user/emails»,»emojis_url»:»https://api.github.com/emojis»,»events_url»:»https://api.github.com/events»,»feeds_url»:»https://api.github.com/feeds»,»followers_url»:»https://api.github.com/user/followers»,»following_url»:»https://api.github.com/user/following{/target}»,»gists_url»:»https://api.github.com/gists{/gist_id}»,»hub_url»:»https://api.github.com/hub»,»issue_search_url»:»https://api.github.com/search/issues?q={query}{&page,per_page,sort,order}»,»issues_url»:»https://api.github.com/issues»,»keys_url»:»https://api.github.com/user/keys»,»notifications_url»:»https://api.github.com/notifications»,»organization_repositories_url»:»https://api.github.com/orgs/{org}/repos{?type,page,per_page,sort}»,»organization_url»:»https://api.github.com/orgs/{org}»,»public_gists_url»:»https://api.github.com/gists/public»,»rate_limit_url»:»https://api.github.com/rate_limit»,»repository_url»:»https://api.github.com/repos/{owner}/{repo}»,»repository_search_url»:»https://api.github.com/search/repositories?q={query}{&page,per_page,sort,order}»,»current_user_repositories_url»:»https://api.github.com/user/repos{?type,page,per_page,sort}»,»starred_url»:»https://api.github.com/user/starred{/owner}{/repo}»,»starred_gists_url»:»https://api.github.com/gists/starred»,»team_url»:»https://api.github.com/teams»,»user_url»:»https://api.github.com/users/{user}»,»user_organizations_url»:»https://api.github.com/user/orgs»,»user_repositories_url»:»https://api.github.com/users/{user}/repos{?type,page,per_page,sort}»,»user_search_url»:»https://api.github.com/search/users?q={query}{&page,per_page,sort,order}»}’ |
Если присмотреться к ответу, можно заметить, что его содержимое является сериализированным JSON контентом. Воспользовавшись словарем, можно взять полученные из .text
строки str
и провести с ними обратную сериализацию при помощи использования json.loads(). Есть и более простой способ, который требует применения .json()
.
>>> response.json() {‘current_user_url’: ‘https://api.github.com/user’, ‘current_user_authorizations_html_url’: ‘https://github.com/settings/connections/applications{/client_id}’, ‘authorizations_url’: ‘https://api.github.com/authorizations’, ‘code_search_url’: ‘https://api.github.com/search/code?q={query}{&page,per_page,sort,order}’, ‘commit_search_url’: ‘https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}’, ’emails_url’: ‘https://api.github.com/user/emails’, ’emojis_url’: ‘https://api.github.com/emojis’, ‘events_url’: ‘https://api.github.com/events’, ‘feeds_url’: ‘https://api.github.com/feeds’, ‘followers_url’: ‘https://api.github.com/user/followers’, ‘following_url’: ‘https://api.github.com/user/following{/target}’, ‘gists_url’: ‘https://api.github.com/gists{/gist_id}’, ‘hub_url’: ‘https://api.github.com/hub’, ‘issue_search_url’: ‘https://api.github.com/search/issues?q={query}{&page,per_page,sort,order}’, ‘issues_url’: ‘https://api.github.com/issues’, ‘keys_url’: ‘https://api.github.com/user/keys’, ‘notifications_url’: ‘https://api.github.com/notifications’, ‘organization_repositories_url’: ‘https://api.github.com/orgs/{org}/repos{?type,page,per_page,sort}’, ‘organization_url’: ‘https://api.github.com/orgs/{org}’, ‘public_gists_url’: ‘https://api.github.com/gists/public’, ‘rate_limit_url’: ‘https://api.github.com/rate_limit’, ‘repository_url’: ‘https://api.github.com/repos/{owner}/{repo}’, ‘repository_search_url’: ‘https://api.github.com/search/repositories?q={query}{&page,per_page,sort,order}’, ‘current_user_repositories_url’: ‘https://api.github.com/user/repos{?type,page,per_page,sort}’, ‘starred_url’: ‘https://api.github.com/user/starred{/owner}{/repo}’, ‘starred_gists_url’: ‘https://api.github.com/gists/starred’, ‘team_url’: ‘https://api.github.com/teams’, ‘user_url’: ‘https://api.github.com/users/{user}’, ‘user_organizations_url’: ‘https://api.github.com/user/orgs’, ‘user_repositories_url’: ‘https://api.github.com/users/{user}/repos{?type,page,per_page,sort}’, ‘user_search_url’: ‘https://api.github.com/search/users?q={query}{&page,per_page,sort,order}’} |
Тип полученного значения из .json()
, является словарем. Это значит, что доступ к его содержимому можно получить по ключу.
Коды состояния и тело сообщения предоставляют огромный диапазон возможностей. Однако, для их оптимального использования требуется изучить метаданные и заголовки HTTP.
HTTP заголовки ответов на запрос могут предоставить определенную полезную информацию. Это может быть тип содержимого ответного пейлоада, а также ограничение по времени для кеширования ответа. Для просмотра HTTP заголовков загляните в атрибут .headers
.
>>> response.headers {‘Server’: ‘GitHub.com’, ‘Date’: ‘Mon, 10 Dec 2018 17:49:54 GMT’, ‘Content-Type’: ‘application/json; charset=utf-8’, ‘Transfer-Encoding’: ‘chunked’, ‘Status’: ‘200 OK’, ‘X-RateLimit-Limit’: ’60’, ‘X-RateLimit-Remaining’: ’59’, ‘X-RateLimit-Reset’: ‘1544467794’, ‘Cache-Control’: ‘public, max-age=60, s-maxage=60’, ‘Vary’: ‘Accept’, ‘ETag’: ‘W/»7dc470913f1fe9bb6c7355b50a0737bc»‘, ‘X-GitHub-Media-Type’: ‘github.v3; format=json’, ‘Access-Control-Expose-Headers’: ‘ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type’, ‘Access-Control-Allow-Origin’: ‘*’, ‘Strict-Transport-Security’: ‘max-age=31536000; includeSubdomains; preload’, ‘X-Frame-Options’: ‘deny’, ‘X-Content-Type-Options’: ‘nosniff’, ‘X-XSS-Protection’: ‘1; mode=block’, ‘Referrer-Policy’: ‘origin-when-cross-origin, strict-origin-when-cross-origin’, ‘Content-Security-Policy’: «default-src ‘none'», ‘Content-Encoding’: ‘gzip’, ‘X-GitHub-Request-Id’: ‘E439:4581:CF2351:1CA3E06:5C0EA741’} |
.headers
возвращает словарь, что позволяет получить доступ к значению заголовка HTTP по ключу. Например, для просмотра типа содержимого ответного пейлоада, требуется использовать Content-Type
.
>>> response.headers[‘Content-Type’] ‘application/json; charset=utf-8’ |
У объектов словарей в качестве заголовков есть своим особенности. Специфика HTTP предполагает, что заголовки не чувствительны к регистру. Это значит, что при получении доступа к заголовкам можно не беспокоится о том, использованы строчным или прописные буквы.
>>> response.headers[‘content-type’] ‘application/json; charset=utf-8’ |
При использовании ключей 'content-type'
и 'Content-Type'
результат будет получен один и тот же.
Это была основная информация, требуемая для работы с Response
. Были задействованы главные атрибуты и методы, а также представлены примеры их использования. В дальнейшем будет показано, как изменится ответ после настройки запроса GET
.
Python Requests параметры запроса
Наиболее простым способом настроить запрос GET
является передача значений через параметры строки запроса в URL. При использовании метода get()
, данные передаются в params
. Например, для того, чтобы посмотреть на библиотеку requests
можно использовать Search API на GitHub.
import requests # Поиск местонахождения для запросов на GitHub response = requests.get( ‘https://api.github.com/search/repositories’, params={‘q’: ‘requests+language:python’}, ) # Анализ некоторых атрибутов местонахождения запросов json_response = response.json() repository = json_response[‘items’][0] print(f‘Repository name: {repository[«name»]}’) # Python 3.6+ print(f‘Repository description: {repository[«description»]}’) # Python 3.6+ |
Передавая словарь {'q': 'requests+language:python'}
в параметр params
, который является частью .get()
, можно изменить ответ, что был получен при использовании Search API
.
Можно передать параметры в get()
в форме словаря, как было показано выше. Также можно использовать список кортежей.
>>> requests.get( ... ‘https://api.github.com/search/repositories’, ... params=[(‘q’, ‘requests+language:python’)], ... ) <Response [200]> |
Также можно передать значение в байтах.
>>> requests.get( ... ‘https://api.github.com/search/repositories’, ... params=b‘q=requests+language:python’, ... ) <Response [200]> |
Строки запроса полезны для уточнения параметров в запросах GET
. Также можно настроить запросы при помощи добавления или изменения заголовков отправленных сообщений.
Для изменения HTTP заголовка требуется передать словарь данного HTTP заголовка в get()
при помощи использования параметра headers
. Например, можно изменить предыдущий поисковой запрос, подсветив совпадения в результате. Для этого в заголовке Accept
медиа тип уточняется при помощи text-match
.
import requests response = requests.get( ‘https://api.github.com/search/repositories’, params={‘q’: ‘requests+language:python’}, headers={‘Accept’: ‘application/vnd.github.v3.text-match+json’}, ) # просмотр нового массива `text-matches` с предоставленными данными # о поиске в пределах результатов json_response = response.json() repository = json_response[‘items’][0] print(f‘Text matches: {repository[«text_matches»]}’) |
Заголовок Accept
сообщает серверу о типах контента, который можно использовать в рассматриваемом приложении. Здесь подразумевается, что все совпадения будут подсвечены, для чего в заголовке используется значение application/vnd.github.v3.text-match+json
. Это уникальный заголовок Accept
для GitHub. В данном случае содержимое представлено в специальном JSON формате.
Перед более глубоким изучением способов редактирования запросов, будет не лишним остановиться на некоторых других методах HTTP.
Примеры HTTP методов в Requests
Помимо GET
, большой популярностью пользуются такие методы, как POST
, PUT
, DELETE
, HEAD
, PATCH
и OPTIONS
. Для каждого из этих методов существует своя сигнатура, которая очень похожа на метод get()
.
>>> requests.post(‘https://httpbin.org/post’, data={‘key’:‘value’}) >>> requests.put(‘https://httpbin.org/put’, data={‘key’:‘value’}) >>> requests.delete(‘https://httpbin.org/delete’) >>> requests.head(‘https://httpbin.org/get’) >>> requests.patch(‘https://httpbin.org/patch’, data={‘key’:‘value’}) >>> requests.options(‘https://httpbin.org/get’) |
Каждая функция создает запрос к httpbin
сервису, используя при этом ответный HTTP метод. Результат каждого метода можно изучить способом, который был использован в предыдущих примерах.
>>> response = requests.head(‘https://httpbin.org/get’) >>> response.headers[‘Content-Type’] ‘application/json’ >>> response = requests.delete(‘https://httpbin.org/delete’) >>> json_response = response.json() >>> json_response[‘args’] {} |
При использовании каждого из данных методов в Response
могут быть возвращены заголовки, тело запроса, коды состояния и многие другие аспекты. Методы POST
, PUT
и PATCH
в дальнейшем будут описаны более подробно.
Python Requests тело сообщения
В соответствии со спецификацией HTTP запросы POST
, PUT
и PATCH
передают информацию через тело сообщения, а не через параметры строки запроса. Используя requests
, можно передать данные в параметр data
.
В свою очередь data
использует словарь, список кортежей, байтов или объект файла. Это особенно важно, так как может возникнуть необходимость адаптации отправляемых с запросом данных в соответствии с определенными параметрами сервера.
К примеру, если тип содержимого запроса application/x-www-form-urlencoded
, можно отправить данные формы в виде словаря.
>>> requests.post(‘https://httpbin.org/post’, data={‘key’:‘value’}) <Response [200]> |
Ту же самую информацию также можно отправить в виде списка кортежей.
>>> requests.post(‘https://httpbin.org/post’, data=[(‘key’, ‘value’)]) <Response [200]> |
В том случае, если требуется отравить данные JSON, можно использовать параметр json
. При передачи данных JSON через json
, requests
произведет сериализацию данных и добавит правильный Content-Type
заголовок.
Стоит взять на заметку сайт httpbin.org. Это чрезвычайно полезный ресурс, созданный человеком, который внедрил использование requests
– Кеннетом Рейтцом. Данный сервис предназначен для тестовых запросов. Здесь можно составить пробный запрос и получить ответ с требуемой информацией. В качестве примера рассмотрим базовый запрос с использованием POST
.
>>> response = requests.post(‘https://httpbin.org/post’, json={‘key’:‘value’}) >>> json_response = response.json() >>> json_response[‘data’] ‘{«key»: «value»}’ >>> json_response[‘headers’][‘Content-Type’] ‘application/json’ |
Здесь видно, что сервер получил данные и HTTP заголовки, отправленные вместе с запросом. requests
также предоставляет информацию в форме PreparedRequest
.
Python Requests анализ запроса
При составлении запроса стоит иметь в виду, что перед его фактической отправкой на целевой сервер библиотека requests
выполняет определенную подготовку. Подготовка запроса включает в себя такие вещи, как проверка заголовков и сериализация содержимого JSON.
Если открыть .request
, можно просмотреть PreparedRequest
.
>>> response = requests.post(‘https://httpbin.org/post’, json={‘key’:‘value’}) >>> response.request.headers[‘Content-Type’] ‘application/json’ >>> response.request.url ‘https://httpbin.org/post’ >>> response.request.body b‘{«key»: «value»}’ |
Проверка PreparedRequest
открывает доступ ко всей информации о выполняемом запросе. Это может быть пейлоад, URL, заголовки, аутентификация и многое другое.
У всех описанных ранее типов запросов была одна общая черта – они представляли собой неаутентифицированные запросы к публичным API. Однако, подобающее большинство служб, с которыми может столкнуться пользователь, запрашивают аутентификацию.
Python Requests аутентификация HTTP AUTH
Аутентификация помогает сервису понять, кто вы. Как правило, вы предоставляете свои учетные данные на сервер, передавая данные через заголовок Authorization
или пользовательский заголовок, определенной службы. Все функции запроса, которые вы видели до этого момента, предоставляют параметр с именем auth
, который позволяет вам передавать свои учетные данные.
Одним из примеров API, который требует аутентификации, является Authenticated User API на GitHub. Это конечная точка веб-сервиса, которая предоставляет информацию о профиле аутентифицированного пользователя. Чтобы отправить запрос API-интерфейсу аутентифицированного пользователя, вы можете передать свое имя пользователя и пароль на GitHub через кортеж в get()
.
>>> from getpass import getpass >>> requests.get(‘https://api.github.com/user’, auth=(‘username’, getpass())) <Response [200]> |
Запрос выполнен успешно, если учетные данные, которые вы передали в кортеже auth
, действительны. Если вы попытаетесь сделать этот запрос без учетных данных, вы увидите, что код состояния 401 Unauthorized
.
>>> requests.get(‘https://api.github.com/user’) <Response [401]> |
Когда вы передаете имя пользователя и пароль в кортеже параметру auth
, вы используете учетные данные при помощи базовой схемы аутентификации HTTP.
Таким образом, вы можете создать тот же запрос, передав подробные учетные данные базовой аутентификации, используя HTTPBasicAuth
.
>>> from requests.auth import HTTPBasicAuth >>> from getpass import getpass >>> requests.get( ... ‘https://api.github.com/user’, ... auth=HTTPBasicAuth(‘username’, getpass()) ... ) <Response [200]> |
Хотя вам не нужно явно указывать обычную аутентификацию, может потребоваться аутентификация с использованием другого метода. requests
предоставляет другие методы аутентификации, например, HTTPDigestAuth
и HTTPProxyAuth
.
Вы даже можете предоставить свой собственный механизм аутентификации. Для этого необходимо сначала создать подкласс AuthBase. Затем происходит имплементация __call__()
.
import requests from requests.auth import AuthBase class TokenAuth(AuthBase): «»»Implements a custom authentication scheme.»»» def __init__(self, token): self.token = token def __call__(self, r): «»»Attach an API token to a custom auth header.»»» r.headers[‘X-TokenAuth’] = f‘{self.token}’ # Python 3.6+ return r requests.get(‘https://httpbin.org/get’, auth=TokenAuth(‘12345abcde-token’)) |
Здесь пользовательский механизм TokenAuth
получает специальный токен. Затем этот токен включается заголовок X-TokenAuth
запроса.
Плохие механизмы аутентификации могут привести к уязвимостям безопасности, поэтому, если службе по какой-то причине не нужен настраиваемый механизм аутентификации, вы всегда можете использовать проверенную схему аутентификации, такую как Basic или OAuth.
Пока вы думаете о безопасности, давайте рассмотрим использование requests
в SSL сертификатах.
Python Requests проверка SSL сертификата
Всякий раз, когда данные, которые вы пытаетесь отправить или получить, являются конфиденциальными, безопасность важна. Вы общаетесь с защищенными сайтами через HTTP, устанавливая зашифрованное соединение с использованием SSL, что означает, что проверка SSL сертификата целевого сервера имеет решающее значение.
Хорошей новостью является то, что requests
по умолчанию все делает сам. Однако в некоторых случаях необходимо внести определенные поправки.
Если требуется отключить проверку SSL-сертификата, параметру verify
функции запроса можно присвоить значение False
.
>>> requests.get(‘https://api.github.com’, verify=False) InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced—usage.html#ssl-warnings InsecureRequestWarning) <Response [200]> |
В случае небезопасного запроса requests
предупреждает о возможности потери информации и просит сохранить данные или отказаться от запроса.
Примечание. Для предоставления сертификатов
requests
использует пакет, который вызываетсяcertifi
. Это дает понятьrequests
, каким ответам можно доверять. Поэтому вам следует часто обновлятьcertifi
, чтобы обеспечить максимальную безопасность ваших соединений.
Python Requests производительность приложений
При использовании requests
, особенно в среде приложений, важно учитывать влияние на производительность. Такие функции, как контроль таймаута, сеансы и ограничения повторных попыток, могут помочь обеспечить бесперебойную работу приложения.
Таймауты
Когда вы отправляете встроенный запрос во внешнюю службу, вашей системе нужно будет дождаться ответа, прежде чем двигаться дальше. Если ваше приложение слишком долго ожидает ответа, запросы к службе могут быть сохранены, пользовательский интерфейс может пострадать или фоновые задания могут зависнуть.
По умолчанию в requests на ответ время не ограничено, и весь процесс может занять значительный промежуток. По этой причине вы всегда должны указывать время ожидания, чтобы такого не происходило. Чтобы установить время ожидания запроса, используйте параметр timeout
. timeout
может быть целым числом или числом с плавающей точкой, представляющим количество секунд ожидания ответа до истечения времени ожидания.
>>> requests.get(‘https://api.github.com’, timeout=1) <Response [200]> >>> requests.get(‘https://api.github.com’, timeout=3.05) <Response [200]> |
В первом примере запрос истекает через 1 секунду. Во втором примере запрос истекает через 3,05 секунды.
Вы также можете передать кортеж. Это – таймаут соединения (время, за которое клиент может установить соединение с сервером), а второй – таймаут чтения (время ожидания ответа, как только ваш клиент установил соединение):
>>> requests.get(‘https://api.github.com’, timeout=(2, 5)) <Response [200]> |
Если запрос устанавливает соединение в течение 2 секунд и получает данные в течение 5 секунд после установления соединения, то ответ будет возвращен, как это было раньше. Если время ожидания истекло, функция вызовет исключение Timeout
.
import requests from requests.exceptions import Timeout try: response = requests.get(‘https://api.github.com’, timeout=1) except Timeout: print(‘The request timed out’) else: print(‘The request did not time out’) |
Ваша программа может поймать исключение Timeout
и ответить соответственно.
Объект Session в Requests
До сих пор вы имели дело с requests
API высокого уровня, такими как get()
и post()
. Эти функции являются абстракцией того, что происходит, когда вы делаете свои запросы. Они скрывают детали реализации, такие как управление соединениями, так что вам не нужно о них беспокоиться.
Под этими абстракциями находится класс под названием Session
. Если вам необходимо настроить контроль над выполнением запросов или повысить производительность ваших запросов, вам может потребоваться использовать Session
напрямую.
Сессии используются для сохранения параметров в запросах.
Например, если вы хотите использовать одну и ту же аутентификацию для нескольких запросов, вы можете использовать сеанс:
import requests from getpass import getpass # используя менеджер контента, можно убедиться, что ресурсы, применимые # во время сессии будут свободны после использования with requests.Session() as session: session.auth = (‘username’, getpass()) # Instead of requests.get(), you’ll use session.get() response = session.get(‘https://api.github.com/user’) # здесь можно изучить ответ print(response.headers) print(response.json()) |
Каждый раз, когда вы делаете запрос session
, после того как он был инициализирован с учетными данными аутентификации, учетные данные будут сохраняться.
Первичная оптимизация производительности сеансов происходит в форме постоянных соединений. Когда ваше приложение устанавливает соединение с сервером с помощью Session
, оно сохраняет это соединение в пуле соединений. Когда ваше приложение снова хочет подключиться к тому же серверу, оно будет использовать соединение из пула, а не устанавливать новое.
HTTPAdapter — Максимальное количество повторов запроса в Requests
В случае сбоя запроса возникает необходимость сделать повторный запрос. Однако requests
не будет делать это самостоятельно. Для применения функции повторного запроса требуется реализовать собственный транспортный адаптер.
Транспортные адаптеры позволяют определить набор конфигураций для каждой службы, с которой вы взаимодействуете. Предположим, вы хотите, чтобы все запросы к https://api.github.com
были повторены три раза, прежде чем, наконец, появится ConnectionError
. Для этого нужно построить транспортный адаптер, установить его параметр max_retries
и подключить его к существующему объекту Session
.
import requests from requests.adapters import HTTPAdapter from requests.exceptions import ConnectionError github_adapter = HTTPAdapter(max_retries=3) session = requests.Session() # использование `github_adapter` для всех запросов, которые начинаются с указанным URL session.mount(‘https://api.github.com’, github_adapter) try: session.get(‘https://api.github.com’) except ConnectionError as ce: print(ce) |
При установке HTTPAdapter
, github_adapter
к session
, session
будет придерживаться своей конфигурации для каждого запроса к https://api.github.com
.
Таймауты, транспортные адаптеры и сессии предназначены для обеспечения эффективности используемого кода и стабильности приложения.
Заключение
Изучение библиотеки Python requests является очень трудоемким процессом.
После разбора данных в статье примеров можно научиться тому, как:
- Создавать запросы, используя различные методы HTTP –
GET
,POST
иPUT
; - Настраивать свои запросы, изменив заголовки, аутентификацию, строки запросов и тела сообщений;
- Проверять данные, которые были отправлены на сервер, а также те данные, которые сервер отправил обратно;
- Работать с проверкой SSL сертификата;
- Эффективно использовать
requests
,max_retries
,timeout
,Sessions
и транспортные адаптеры.
Грамотное использование requests позволит наиболее эффективно настроить разрабатываемые приложения, исследуя широкий спектр веб-сервисов и данных, опубликованных на них.
- Данная статья является переводом статьи: Python’s Requests Library (Guide)
- Изображение статьи принадлежит сайту © RealPython
Являюсь администратором нескольких порталов по обучению языков программирования Python, Golang и Kotlin. В составе небольшой команды единомышленников, мы занимаемся популяризацией языков программирования на русскоязычную аудиторию. Большая часть статей была адаптирована нами на русский язык и распространяется бесплатно.
E-mail: vasile.buldumac@ati.utm.md
Образование
Universitatea Tehnică a Moldovei (utm.md)
- 2014 — 2018 Технический Университет Молдовы, ИТ-Инженер. Тема дипломной работы «Автоматизация покупки и продажи криптовалюты используя технический анализ»
- 2018 — 2020 Технический Университет Молдовы, Магистр, Магистерская диссертация «Идентификация человека в киберпространстве по фотографии лица»
Прежде чем загрузить содержимое страницы, робот поисковой системы (или браузер пользователя) сначала делает специальный запрос, на который сервер отвечает в виде трехзначного кода. Разбираемся, какие эти коды бывают и как их проверить — вручную и с помощью сторонних сервисов.
Что такое код сервера
Код сервера (его еще называют кодом состояния HTTP) — последовательность из трех чисел с небольшим текстовым пояснением, который запрашивают и проверяют браузеры и поисковые роботы. Вот пример как это выглядит:
Страница с кодом ответа сервера Discord при переходе на несуществующую страницу
В этом случае код — число 404. Оно означает, что запрашиваемая страница не существует. Под числом небольшое текстовое сообщение: «вы выглядите потерянным, вот вам несколько других страниц». Под сообщением — альтернатива: ссылки на существующие страницы.
Читайте также: 11 способов проверки битых ссылок на сайте
Какие бывают коды ответов
Классы состояния — это группы кодов, которые объединяются общими признаками. Всего есть пять классов: принадлежность определяется первой цифрой из трех.
Класс 1. Выглядит так: 1ХХ. Это временные информационные коды. Они сообщают о том, что запрос принят и находится в обработке.
Класс 2. Выглядит так: 2ХХ. Сообщает об успешной обработке запроса.
Класс 3. Выглядит так: 3ХХ. Сообщает о перенаправлении с одного адреса на другой. Эти коды говорят об изменении URL. Используются при создании зеркал или переносе сайта на новый движок.
Класс 4. Выглядит так: 4ХХ. Говорит об ошибке со стороны посетителя. Обычно после числа идет небольшой текст с объяснением — в чем проблема. Такие коды говорят о запрете просмотра страницы или об ее отсутствии.
Класс 5. Выглядит так: 5ХХ. Сообщает об ошибке со стороны сервера. После этого класса тоже следует текстовое сообщение с объяснением причины поломки.
Теперь разберем более распространенные виды ответов в каждом классе.
Класс 1
100 Continue. Промежуточный ответ сервера. Говорит о том, что сервер принял запрос и начинает обработку.
101 Switching Protocols. Код ответа указывает протокол, который переключает сервер, используя запрос Upgrade. В ответ сервер отправляет заголовок ответа Upgrade с указанием протокола, на который переключился.
102 Processing. Это значит, что сервер получил запрос и обрабатывает его. Клиент не должен разрывать соединение, чтобы дождаться ответа от сервера. Этот код используется в протоколе WebDAV (измененный HTTP для работы с файлами).
Класс 2
200 Ok. Говорит об успешной обработке запроса. Например, запрошенные страница или данные найдены и готовы к просмотру. Всем страницам, которые участвуют в индексировании, присваивается код 200.
202 Accepted. Запрос принят и будет обрабатываться долго. Пользователь может не дожидаться окончания запроса. Используется, когда запрос обрабатывается другим сервером. Такой код используется сервером, чтобы выполнять несколько запросов одновременно: пока пользователь с кодом 202 ждет окончания операции, 200 уже «видит» страницу.
203 Non-Authoritative Information. Код означает, что обработка запроса прошла успешно. Но информация поступила не от сервера, а от другого источника: облака, резервной копии.
204 No Content. Такой код используется на портал для запуска скриптов. Например, когда пользователь кликает по свободному месту на сайте.
205 Reset Content. Говорит о том, что браузеру нужно очистить форму, в которую вписаны данные. Такой код используется, чтобы очистить поля, заполненные при регистрации. При это обновлять ресурс не нужно.
Класс 3
300 Multiple Choices. Говорит о том, что указанный URL обозначает больше, чем один ресурс. Например, страницу, переведенную на несколько языков.
301 Moved Permanently. Ответ означает, что запрошенный URL изменен или больше не существует, а пользователю предлагается перейти по новой ссылке.
Обычно с таким ответом срабатывает автоматический редирект на новую страницу. Код 301 уместно прописывать в следующих ситуациях: когда сайт переезжает на новый домен, при склеивании зеркала с оригинальным сайтом, при изменении ссылок страниц, для маскировки партнерских ссылок. Не нужно прописывать код, если в скором времени сайт вернется на прежний URL.
302 Found. Запрошенный URL перенесен на новый адрес. Такой код используется, когда адрес страницы изменился, но контент индексируется по старой ссылке. Например, 302 используют, чтобы было несколько версий главной страницы на разных языках. Также код говорит о том, что в будущем сайт будет доступен по старому адресу.
303 See Other. Указывает, что происходит перенаправление на другую страницу. Чтобы новая страница индексировалась, она должна отвечать на код 200. Такой код используется для страниц с подтверждением. Например, когда сайт высылает код подтверждения регистрации.
304 Not Modified. Это значит, что предыдущая версия страницы не изменена. Благодаря этому робот индексирует ее без загрузки. Из-за этого сервер меньше нагружается и повышается время безотказной работы. А пользователь работает с версией страницы, которая сохранена в памяти браузера.
У пользователей часто возникает ошибка HTTP 304. Такое бывает, если компьютер заражен вирусами или Windows медленно работает. Чтобы решить проблему, нужно проверить ПК на вирусы и очистить от лишних файлов. Еще можно восстановить записи в реестре системы. Но такую процедуру лучше доверить мастерам сервисного центра: если делать самостоятельно, можно превратить ПК в «кирпич».
305 Use Proxy. Сайт будет доступен только при использовании прокси-сервера. При этом нужно использовать сервер, который указан в разделе Location. Такой код предназначен для защиты сайта.
308 Permanent Redirect. Полностью повторяет запрос 301. Разница в методе выполняемого запроса.
Класс 4
400 Bad Request. Сервер не может понять запрос, потому что он введен с ошибкой. Под ошибкой обычно понимается синтаксическая: некорректно введен URL. Также код 400 появляется, когда пользователь пытается загрузить на сайт слишком большой файл. Решить проблему помогает смена запроса или очистка cookies. Чтобы очистить куки в браузере, нужно перейти в настройки, в раздел конфиденциальности и безопасности.
401 Unauthorized. У клиента не получается зайти на страницу сайта, потому что у него не хватает прав доступа. Такая ошибка возникает на сайтах, где есть форма для авторизации. Решить ошибку можно двумя способами: войти в систему с использованием логина и пароля или очистить кэш браузера.
403 Forbidden. Этот код говорит о запрете на просмотр страницы. Такое бывает, если для IP-адреса внесен запрет на уровне сервера. Решить проблему можно с помощью VPN или прокси.
Что такое прокси? Как выбрать качественный прокси-сервер? Прокси для SEO, парсинга, арбитража и пр.
404 Not Found. Код означает, что запрашиваемая страница (сайт или документ) не существует или расположена по другому адресу.
Ошибка 404 влияет на SEO-оптимизацию: если страница не существует / не доступна, поисковые роботы не будут ее индексировать и показывать в поиске. А еще переходы по битым ссылкам ухудшают поведенческие факторы. Но нивелировать негатив поможет грамотное оформление 404-страницы. Можно сделать ее с юмором, перенаправить трафик на другие ресурсы.
405 Method Not Allowed. Соответствующий код появляется, если на этапе обработки запроса сервер получает запрет. Такое случается, если нарушается работа php-скриптов. Ошибку можно решить с помощью перезагрузки страницы. Также помогает проверить все скрипты и удалить дополнения в CMS.
408 Request Timeout. Это значит, что сервер прервал соединение. Такое бывает, когда сервер не получает запросов от посетителей долгое время. Если пользователь сам прекращает соединение, ошибки не возникает.
409 Conflict.Означает конфликт между пользовательским запросом и сервером. Например, клиент хочет скачать с сайта файл «фото01». Но раньше файл назывался «фото1» и это название сохранилось в кеше. Из-за этого сервер не понимает, что хочет скачать пользователь — возникает конфликт.
410 Gone. Это значит, что документ удален с сервера навсегда. Если поисковый робот получит этот код, он больше не будет просматривать страницу.
413 Request Entity Too Large. Ошибка возникает, если пользователь пытается загрузить слишком большой файл на сайт. Стандартно допустимый размер загружаемого файла — 1 Мб. Если клиент пытается загрузить больше — возникает ошибка. Чтобы решить проблему, нужно увеличить размер максимально загружаемого файла. Для этого нужно вносить изменения в настройки Nginx, php и apache. (Есть видео, как это делать в CMS WordPress.)
414 Request-URL Too Long. Если пользователь пытается сделать запрос с длинным URL, возникает такая ошибка.
423 Locked. Такая ошибка возникает, если IP-адрес блокируется хостером. Блокировку можно получить за сильную активность, интернет-мошенничество или вирусы.
451 Unavailable For Legal Reasons. Новая ошибка, которая набирает популярность. Она появляется на сайтах, которые заблокированы государством. Ошибка 451 — дополнение к 403.
Класс 5
500 Internal Server Error. Ошибка из-за сбоев на сервере. Возникает при неправильной конфигурации файла .htaccess. Чтобы решить проблему, нужно изменить директиву Options: поставить в начале строки #.
502 Bad Gateway. Возникает, если есть промежуточный сервер. Случается, когда промежуточный сервер получает запрос и запрашивает данные у «главного» сервера, и получает неправильный ответ. В решении ошибки помогает очистка кеша браузера, обновление страницы и очистка DNS-кеша.
503 Service Unavailable. У сервера не получается обрабатывать запросы по техническим причинам. Например, если на сервере ведутся какие-то работы.
504 Gateway Timeout. Шлюз не дает ответа. Появляется, если ответ от главного сервера не получен.
507 Insufficient Storage. Ошибка высвечивается, если у сервера нет места работы с операцией. Проблему можно решить перезагрузкой. Или просто подождать.
511 Network Authentication Required. Значит, что нужно пройти авторизацию для доступа к интернету. Такой ответ высылает посредник, например, провайдер. Чтобы решить проблему, нужно написать в поддержку провайдера.
О популярных и важных ошибках поговорили. Теперь разберемся, как проверить код сервера. Это можно сделать самостоятельно или с помощью сторонних программ.
Как проверить код сервера
Начнем с ручного способа. Для этого перейдите на сайт через браузер Chrome и откройте консоль клавишей «F12». (Или «Fn + F12» на ноутбуках. Также инструменты разработчика можно включить сочетанием клавиш «Ctrl + Shift + I».) Теперь перейдите во вкладку «Network» и нажмите «Ctrl + R».
Ручная проверка кодов ответа страниц в консоли
Чтобы узнать код страницы, нужно смотреть столбец «Status».
Коды ответа сервера в столбце Status
Теперь о проверках с помощью сторонних сайтов и плагинов.
Bertal
Bertal — сервис для просмотра http-заголовков, веб-файлов (.html, .php, .asp, .gif, .jpg, .css и др.). Также позволяет просматривать html-код страниц. Работает с протоколами HTTP, HTTPS, FTP.
Возможности:
- Запрос информации методами HEAD, GET, POST. Метод HEAD — если запрашивается заголовок. GET — если запрашивается заголовок и тело. POST — как и GET, но с заполненной строкой POST.
- Поддерживаемые поисковые роботы: YandexBot, GoogleBot, BingBot, Yahoo, Baiduspider.
- Поддерживаемые браузеры: Mozilla Firefox, Google Chrome, Internet Explorer, Opera, Opera mini.
- Работает с Proxy.
- Можно указывать содержимое Cookies.
Отчет по странице от Bertal
Стоимость. Бесплатно.
PR-CY
PR-CY — cервис для SEO-аудита сайта, мониторинга и проверки позиций в поисковой выдачи. Подходит для анализа кодов ответа сервера, метатегов, содержимого страниц. Есть функции мониторинга сайта, проверки индексирования.
Возможности:
- Проверка кодов ответа страниц. Сервис проверяет все элементы: текст, скрипты, видео, фотографии. После PR-CY дает рекомендации: сжать текст, сократить HTML, CSS или JS.
- Работает с видами запросов: GET, POST, HEAD.
- Глубокий анализ: проверка редиректов, поиск всех кодов.
- Работает с поисковыми системами Google и Yandex.
- Проверка контента: пустые заголовки, лишние скрипты, нерабочие внешние ссылки.
Еще у PR-CY есть много чего: проверка скорости загрузки, вирусов, срока действия SSL-сертификата и др.
Результаты анализа сайта в PR-CY
Стоимость. Есть бесплатный тариф для экспресс-анализа сайта. Для полного аудита нужно покупать подписку. Она стартует от 990 ₽ в месяц. Позволяет вести до 5 проектов и проверять 1 000 страниц. Дорогие тарифы отличаются тем, что можно вести больше проектов и проверять больше страниц.
Читайте также: Как оптимизировать изображения для сайта
Checkmy
Checkmy — помогает проверить коды и заголовки ответа сервера. А еще доступность URL адресов, кеширование страниц, сжатие контента, исходный код, тип сервера и корректность переадресаций.
Возможности:
- Работает с доменам на кириллице.
- Работает через мобильную версию.
- Проверяет страницы с несколькими редиректами.
- Показывает размер и скорость загрузки страницы.
- Проверяет контент на сжатие.
Проверка кодов ответа сервера через Chekmy
Стоимость. Бесплатно.
Sitechecker
Sitechecker подходит для мониторинга сайта и полного аудита.
Возможности:
- Проверка состояния страницы и кодов ответа.
- Подсчет «веса» HTML-кода страницы. Если он больше 2 Мб, сервис подскажет, как его уменьшить.
- Отдельная проверка страницы с кодом 404.
- Проверка индексации поисковыми системами.
- SEO-анализ страницы: проверка title, description, заголовков h1-h6. Проверка изображений и атрибутов Alt, внутренних и внешних ссылок.
- SEO-аудит сайта: оценка битых ссылок и редиректов, метатегов, скорости загрузки.
- Мониторинг ресурса: контроль статуса индексирования, защита от взломов и отслеживание сайтов конкурентов.
Аудит сайта не сервисе Sitecheker
Стоимость. Можно сделать проверку кодов бесплатно. Но функции мониторинга, проверки обратных ссылок и индексации будут недоступны. Платная подписка стартует от 29 $ в месяц. Для подписки доступно 3 тарифа. Они отличаются количеством сайтов, которые можно проверять.
А еще за парсингом метатегов и заголовков, анализом индексации страниц, съемом позиций в поисковиках, сбором семантического ядра можно обратиться в Promopult. Это мощная платформа для комплексного продвижения в интернете: поисковой оптимизации, контекстной и таргетированной рекламы, управления репутацией.
Яндекс.Вебмастер
Яндекс.Вебмастер поможет узнать, доступны ли страницы для поисковых роботов Яндекса. (Но ответ, полученный через Яндекс.Вебмастер, может отличаться от того, который получит поисковый робот. Дело в том, что инструмент работает через другой IP-адрес. Об этом сказано в Яндекс.Справке.)
Возможности:
- Проверка всех классов ответа сервера.
- Дополнительно можно узнать срок действия SSL-сертификата.
- Проверяет страницы размером до 10 Мб.
- Работает с файлами этих типов: PDF, DOC/DOCX, XLS/XLSX, PPT/PPTX, ODS, ODP, ODT, ODG, RTF, TXT и SWF.
Проверка ответа сервера через Яндекс.Вебмастер
Стоимость. Бесплатно.
Converseo
Converseo подходит для как для проверки одиночного URL, так и для массового отслеживания.
Возможности:
- Работа с методами GET, POST, HEAD.
- Есть дополнительные функции: сравнение списков, загрузка фото из Instagram.
- Готовый отчет можно скачать в формате CSV.
Вот так выглядит отчет по массовой проверке URL на сайте Converseo.
Вот так выглядит отчет по одиночной проверке URL на сайте Converseo.
Стоимость. Бесплатно.
Coolakov
Coolakov — работает также, как и Converseo. Есть и дополнительные функции.
Возможности:
- Массовая проверка URL. Особенность в том, что выдается конечный ответ сервера. Например, если был редирект на рабочую страницу — ответ будет 200. Если на сломанную — в зависимости от ошибки.
- Поддерживаемые браузеры: Mozilla Firefox, Google Chrome, Safari.
- Проверка доступности сайта.
- Измерение скорости загрузки портала.
- Проверка индекса качества сайта.
- Проверка орфографии.
Проверка ответов сервера через Coolakov
Стоимость. Бесплатно.
Headmasterseo
Headmasterseo. Программа для Windows и Mac, которая проверяет массовые URL. Отслеживает коды состояния, редиректы, время ответа и заголовки ответов.
Возможности:
- Проверка URL с помощью метода HEAD.
- Одновременная проверка 500 ссылок.
- Проверка циклов перенаправления. Есть тестер, который оценит, правильно ли настроен редирект.
- Работает с прокси.
- Готовый отчет можно экспортировать в формате CSV.
- Проверка полей заголовков.
- Проверка Sitemap файлов в формате XML.
Пример отчета в Headmasterseo
Стоимость. До 500 URL можно проверять бесплатно. Чтобы проверить больше, нужно платить. За 10 000 URL придется заплатить 50 $. За 100 000 — 100 $. Неограниченное количество ссылок можно проверять за 150 $.
Читайте также: Исчерпывающий гид по поисковым операторам Google и Яндекса
Плагины
Redirect Path Link. Это бесплатный плагин для Google Chrome. Он поможет провести SEO-аудит сайта и проверить HTTP-заголовки. Работает только с 3 классом кодов сервера.
Robots Exclusion Checker. Помогает оптимизировать сайт, найти проблемы в индексации и сделать SEO-аудит. Плагин бесплатный. Работает со всеми классами кодов и поисковыми роботами Googlebot, Bing, Yahoo.
SEO META in 1 CLICK. Бесплатный плагин для Google Chrome. Помогает проверить коды ответа сервера, проанализировать заголовки H1-H6, проверить изображения и Alt атрибуты к ним и др.
Website SEO Checker: Free Audit & Analysis. Бесплатный плагин от Sitecheker. В нем есть такие же функции, как и на сайте: аудит, мониторинг, анализ, просмотр кодов ответа и т.д.
Коротко о главном
Код ответа сервера — это трехзначное число с небольшим текстовым сопровождением. Коды делят на 5 классов:
- 1ХХ — информационные.
- 2ХХ — успешные.
- 3ХХ — переадресация
- 4ХХ — проблемы со стороны пользователя.
- 5ХХ — проблемы со стороны сервера.
Это важный элемент поисковой оптимизации. Они влияют на индексирование страницы поисковыми роботами, помогают настроить эффективную переадресацию.
Чтобы сайт хорошо продвигался в поисковых системах, стоит регулярно отслеживать коды ответа. Это можно делать самостоятельно или с помощью сторонних сервисов. Большая часть из них бесплатная.
А чтобы глубже разобраться в SEO, приходите учиться в CyberMarketing. У нас есть статьи, вебинары, базовые и продвинутые курсы по поисковому продвижению. Преподают эксперты Promopult: Руслан Байбеков и Евгений Костин.