What for ?
From the code of your application, you can log in to any web portal. This may be needed when you want to access the resources of your account.
What can you get on this portal?
You can get a list of your trips, or you can check what trips are planned on the entire portal from point "A" to point "B" for a specific date. You can do more.
What do you need?
Local proxy server, I recommend Fiddler - simple and convenient
Visual Studio
We collect data
web- web- HTTP. HTTP , . . Fiddler. Fiddler , blablacar.ru, HTTP- ( ).
. .
HTTP- HttpWebRequest. : GetRequest PostRequest.
GetRequest
public class GetRequest
{
private HttpWebRequest _request;
public void Run(ref CookieContainer cookies)
{
_request = (HttpWebRequest)WebRequest.Create(Address);
_request.Headers.Add("DNT", "1");
_request.Method = "Get";
_request.Accept = Accept;
_request.Host = Host;
if (TurnOffProxy) _request.Proxy = null;
else _request.Proxy = Proxy;
if (UseUnsafeHeaderParsing)
{
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
var settings = (SettingsSection)config.GetSection("system.net/settings");
settings.HttpWebRequest.UseUnsafeHeaderParsing = true;
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("system.net/settings");
}
_request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
if (!ContentType.IsEmpty()) _request.ContentType = ContentType;
if (TimeOut > 0)
{
_request.Timeout = TimeOut;
_request.ReadWriteTimeout = TimeOut;
}
else
{
_request.Timeout = 35000;
_request.ReadWriteTimeout = 35000;
}
if (NoCachePolicy == false)
{
var noCachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore);
_request.CachePolicy = noCachePolicy;
}
foreach (KeyValuePair<string, string> keyValuePair in Headers)
{
_request.Headers.Add(keyValuePair.Key, keyValuePair.Value);
}
if (UserAgent == null) _request.UserAgent = Data.Ie11;
else _request.UserAgent = UserAgent;
if (AllowAutoRedirect != null)
_request.AllowAutoRedirect = (bool)AllowAutoRedirect;
if (KeepAlive != null)
_request.KeepAlive = (bool)KeepAlive;
if (Expect100Continue != null)
_request.ServicePoint.Expect100Continue = (bool)Expect100Continue;
if (!Referer.IsEmpty())
_request.Referer = Referer;
_request.CookieContainer = cookies;
try
{
HttpWebResponse response = (HttpWebResponse)_request.GetResponse();
if ((response.StatusCode == HttpStatusCode.OK || response.StatusCode == HttpStatusCode.Moved || response.StatusCode == HttpStatusCode.Redirect) && response.ContentType.StartsWith("image", StringComparison.OrdinalIgnoreCase))
{
// if the remote file was found, download oit
using (Stream inputStream = response.GetResponseStream())
{
byte[] buffer = new byte[64000];
int bytesRead;
bytesRead = inputStream.Read(buffer, 0, buffer.Length);
Response = Convert.ToBase64String(buffer, 0, bytesRead);
}
}
else
{
var stream = response.GetResponseStream();
if (stream != null) Response = new StreamReader(stream).ReadToEnd();
ResponseHeaders = response.Headers;
RequestHeaders = _request.Headers;
}
response.Close();
}
catch (WebException ex)
{
using (var stream = ex.Response.GetResponseStream())
using (var reader = new StreamReader(stream))
{
Response = reader.ReadToEnd();
}
}
catch (Exception ex)
{
}
}
Dictionary<string, string> Headers = new Dictionary<string, string>();
public void AddHeader(string headerName, string headerValue)
{
Headers[headerName] = headerValue;
}
public bool NoCachePolicy { get; set; }
public bool AcceptGZipEncoding { get; set; }
public bool UseUnsafeHeaderParsing { get; set; }
public string Address { get; set; }
public string Accept { get; set; }
public string Referer { get; set; }
public string Host { get; set; }
public bool? KeepAlive { get; set; }
public string ContentType { get; set; }
public bool? Expect100Continue { get; set; }
public string Response { get; private set; }
public bool? AllowAutoRedirect { get; set; }
public WebHeaderCollection ResponseHeaders { get; private set; }
public WebHeaderCollection RequestHeaders { get; private set; }
public string UserAgent { get; set; }
public WebProxy Proxy { get; set; }
public bool TurnOffProxy { get; set; }
public int TimeOut { get; set; }
}
PostRequest
public class PostRequest
{
private HttpWebRequest _request;
public void Run(ref CookieContainer cookies)
{
_request = (HttpWebRequest)WebRequest.Create(Address);
_request.Method = "POST";
_request.Host = Host;
_request.Headers.Add("DNT", "1");
_request.Proxy = Proxy;
_request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
if (TimeOut > 0)
{
_request.Timeout = TimeOut;
_request.ReadWriteTimeout = TimeOut;
}
else
{
_request.Timeout = 90000;
_request.ReadWriteTimeout = 90000;
}
var noCachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore);
_request.CachePolicy = noCachePolicy;
if (Expect100Continue == true) _request.ServicePoint.Expect100Continue = true;
else _request.ServicePoint.Expect100Continue = false;
_request.ContentType = ContentType;
_request.Accept = Accept;
_request.Referer = Referer;
_request.KeepAlive = KeepAlive;
foreach (KeyValuePair<string, string> keyValuePair in Headers)
{
_request.Headers.Add(keyValuePair.Key, keyValuePair.Value);
}
_request.CookieContainer = cookies;
if (UserAgent == null) _request.UserAgent = Dom.Catalog.Data.Ie11;
else _request.UserAgent = UserAgent;
if (AllowAutoRedirect != null)
_request.AllowAutoRedirect = (bool)AllowAutoRedirect;
byte[] sentData;
if (ByteData != null) sentData = ByteData;
else sentData = Encoding.UTF8.GetBytes(Data);
_request.ContentLength = sentData.Length;
Stream sendStream = _request.GetRequestStream();
sendStream.Write(sentData, 0, sentData.Length);
sendStream.Close();
WebResponse response = _request.GetResponse();
ResponseHeaders = response.Headers;
RequestHeaders = _request.Headers;
Stream stream = response.GetResponseStream();
if (stream != null)
{
if (ResponseEncoding.IsEmpty()) Response = new StreamReader(stream).ReadToEnd();
else Response = new StreamReader(stream, Encoding.GetEncoding(ResponseEncoding)).ReadToEnd();
}
response.Close();
}
Dictionary<string, string> Headers = new Dictionary<string, string>();
public void AddHeader(string headerName, string headerValue)
{
Headers[headerName] = headerValue;
}
public bool NoCachePolicy { get; set; }
public string Response { get; set; }
public string ResponseEncoding { get; set; }
public string Data { get; set; }
public byte[] ByteData { get; set; }
public string Address { get; set; }
public string Accept { get; set; }
public string Host { get; set; }
public string ContentType { get; set; }
public string Referer { get; set; }
public bool KeepAlive { get; set; }
public bool? Expect100Continue { get; set; }
public string UserAgent { get; set; }
public bool? AllowAutoRedirect { get; set; }
public WebHeaderCollection ResponseHeaders { get; private set; }
public WebHeaderCollection RequestHeaders { get; private set; }
public WebProxy Proxy { get; set; }
public int TimeOut { get; set; }
}
user password .
cookies cookie .
proxy - . , "127.0.0.1:8888" - Fiddler.
SecurityProtocolType.Tls12 - .
var user = "user"; // !!! rewrite value from your account !!!
var password = "password"; // !!! rewrite value from your account !!!
// We keep cookies here
var cookies = new CookieContainer();
// Any proxy, for example Fiddler
var proxy = new WebProxy("127.0.0.1:8888");
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
cookie , "https://www.blablacar.ru/".
var getRequest = new GetRequest()
{
Address = "https://www.blablacar.ru/",
Accept = "text/html, application/xhtml+xml, image/jxr, */*",
Host = "www.blablacar.ru",
KeepAlive = true,
UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko",
Proxy = proxy
};
getRequest.Run(ref cookies);
, "visitorId":
var visitorStart = getRequest.Response.IndexOf("visitorId") + 12;
var visitorEnd = getRequest.Response.IndexOf("\"", visitorStart);
var visitorId = getRequest.Response.Substring(visitorStart, visitorEnd - visitorStart);
xCorrelationId GUID.
.
// Random value
var xCorrelationId = Guid.NewGuid();
// Auth request
var data = $"{{\"login\":\"{user}\",\"password\":\"{password}\",\"rememberMe\":true,\"grant_type\":\"password\"}}";
var postRequest = new PostRequest()
{
Data = data,
Address = $"https://auth.blablacar.ru/secure-token",
Accept = "application/json",
Host = "auth.blablacar.ru",
ContentType = "application/json",
Referer = "https://www.blablacar.ru/login/email",
KeepAlive = true,
Proxy = proxy
};
postRequest.AddHeader("x-client", "SPA|1.0.0");
postRequest.AddHeader("x-correlation-id", xCorrelationId.ToString());
postRequest.AddHeader("x-currency", "RUB");
postRequest.AddHeader("x-forwarded-proto", "https");
postRequest.AddHeader("x-locale", "ru_RU");
postRequest.AddHeader("x-visitor-id", visitorId);
postRequest.AddHeader("Origin", "https://www.blablacar.ru");
postRequest.Run(ref cookies);
POST- , "bearerCookieValue". "Set-Cookie" .
var bearerCookieValue = string.Empty;
var headers = postRequest.ResponseHeaders;
for (int i = 0; i < headers.Count; ++i)
{
string header = headers.GetKey(i);
if (header == "Set-Cookie")
{
var headerValue = headers.GetValues(i)[0];
headerValue = WebUtility.UrlDecode(headerValue);
var accessTokenStart = postRequest.Response.IndexOf("access_token") + 15;
var accessTokenEnd = postRequest.Response.IndexOf("\"", accessTokenStart);
bearerCookieValue = postRequest.Response.Substring(accessTokenStart, accessTokenEnd - accessTokenStart);
}
}
Now everything is ready to fulfill requests for the necessary information. All the code is generated based on the viewed request / response headers in the Fiddler proxy.
getRequest = new GetRequest()
{
Address = "https://edge.blablacar.ru/bookings-and-tripoffers?active=false",
Accept = "application/json",
Host = "edge.blablacar.ru",
KeepAlive = true,
ContentType = "application/json",
Referer = "https://www.blablacar.ru/rides/history",
Proxy = proxy
};
getRequest.AddHeader("x-blablacar-accept-endpoint-version", "2");
getRequest.AddHeader("x-client", "SPA|1.0.0");
getRequest.AddHeader("x-correlation-id", xCorrelationId.ToString());
getRequest.AddHeader("x-currency", "RUB");
getRequest.AddHeader("x-forwarded-proto", "https");
getRequest.AddHeader("x-locale", "ru_RU");
getRequest.AddHeader("x-visitor-id", visitorId);
getRequest.AddHeader("authorization", $"Bearer {bearerCookieValue}");
getRequest.AddHeader("Origin", "https://www.blablacar.ru");
getRequest.Run(ref cookies);
We receive the response in the form of JSON format:
We find a list of all trips on the portal
In this example, we will find a list of all trips from Moscow to St. Petersburg on December 15, 2020.
var date = "2020-12-15";
var searchUid = Guid.NewGuid();
getRequest = new GetRequest()
{
Address = $"https://edge.blablacar.ru/trip/search?from_coordinates=55.755826%2C37.617299&from_country=RU&to_coordinates=59.931058%2C30.360909&to_country=RU&departure_date={date}&min_departure_time=00%3A00%3A00&requested_seats=1&passenger_gender=UNKNOWN&search_uuid={searchUid}",
Accept = "application/json",
Host = "edge.blablacar.ru",
KeepAlive = true,
ContentType = "application/json",
Referer = "https://www.blablacar.ru/",
Proxy = proxy
};
getRequest.AddHeader("x-blablacar-accept-endpoint-version", "2");
getRequest.AddHeader("x-client", "SPA|1.0.0");
getRequest.AddHeader("x-correlation-id", xCorrelationId.ToString());
getRequest.AddHeader("x-currency", "RUB");
getRequest.AddHeader("x-forwarded-proto", "https");
getRequest.AddHeader("x-locale", "ru_RU");
getRequest.AddHeader("x-visitor-id", visitorId);
getRequest.AddHeader("authorization", $"Bearer {bearerCookieValue}");
getRequest.AddHeader("Origin", "https://www.blablacar.ru");
getRequest.Run(ref cookies);
In response to the request, we receive a JSON string with trips on the portal: