skivan
07.04.2010, 12:35
Всем привет,
Хочу поделиться радостью :p
Изучая C#, решил начать с простых вещей, так что первая статья в этом направлении будет про автоматическую регистрацию почтового ящика на qip.ru.
Собственно, как оказалось, все очень даже просто.
Первым делом необходимо создать класс для работы с http.
Класс нужен для того чтобы облегчить нам отправку и получение http запросов с сохранностью cookie.
public class HTTPClient
{
private CookieCollection Cooks = new CookieCollection();
public HTTPClient(string session_cookiename)
{
}
public void ClearCookie()
{
}
public HttpWebResponse Request(string sUrl)
{
return Request(sUrl, true);
}
public HttpWebResponse Request_Post(string path, string post_body)
{
return Request_Post(path, post_body, true);
}
public HttpWebResponse Request_Post(string path, string post_body, bool bAutoRedirect)
{
try
{
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(path);
httpWebRequest.Proxy = new WebProxy("x.x.x.x", 3128);
httpWebRequest.Proxy.Credentials = new NetworkCredential("username", "password","domain");
httpWebRequest.AllowAutoRedirect = bAutoRedirect;
httpWebRequest.CookieContainer = new CookieContainer();
if (Cooks != null)
{
httpWebRequest.CookieContainer.Add(Cooks);
}
httpWebRequest.Method = "POST";
httpWebRequest.ContentType = "application/x-www-form-urlencoded";
byte[] ByteQuery = System.Text.Encoding.ASCII.GetBytes(post_body);
httpWebRequest.ContentLength = ByteQuery.Length;
Stream QueryStream = httpWebRequest.GetRequestStream();
QueryStream.Write(ByteQuery, 0, ByteQuery.Length);
QueryStream.Close();
HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
httpWebResponse.Cookies = httpWebRequest.CookieContainer.GetCookies(httpWebR equest.RequestUri);
if (httpWebResponse.Cookies != null)
{
Cooks.Add(httpWebResponse.Cookies);
}
return httpWebResponse;
}
catch (WebException ex)
{
return ex.Response as HttpWebResponse;
}
}
public HttpWebResponse Request(string sUrl, bool bAutoRedirect)
{
try
{
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(sUrl);
httpWebRequest.Proxy = new WebProxy("x.x.x.x", 3128);
httpWebRequest.Proxy.Credentials = new NetworkCredential("username", "password", "domain");
httpWebRequest.AllowAutoRedirect = bAutoRedirect;
httpWebRequest.CookieContainer = new CookieContainer();
if (Cooks != null)
{
httpWebRequest.CookieContainer.Add(Cooks);
}
HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
httpWebResponse.Cookies = httpWebRequest.CookieContainer.GetCookies(httpWebR equest.RequestUri);
if (httpWebResponse.Cookies != null)
{
Cooks.Add(httpWebResponse.Cookies);
}
return httpWebResponse;
}
catch (WebException ex)
{
return ex.Response as HttpWebResponse;
}
}
}
Класс содержит CookieCollection и 2 функции возвращающие HttpWebResponse:
Одна с POST запросом, вторая без.
Так же для автоматического распознования понадобится класс работы с antigate. Отдельное спасибо elw.
class anticaptcha
{
public bool debug = false;
public string host = "antigate.com";
public string key;
public string proxy = "";
public string proxy_username = "";
public string proxy_password = "";
public int phrase = 0; // у капчи 2-4 слова = 1
public int regsense = 0; // текст капчи чувствителен к регистру = 1
public int numeric = 0; // капча состоит только с цифр = 1,
// на капче нет цифр = 2
public int calc = 0; // цифры на капче должны быть сплюсованы = 1
public int min_len = 0; // минимальная длину текста капчи
public int max_len = 0; // максимальная длина текста капчи
private string proxy_host = "";
private int proxy_port;
private string result_headers;
private string result_page;
private HttpWebRequest ua;
private string last_cap_id;
public string rec(string filename)
{
ua = browser("http://" + host + "/in.php");
ua.Method = "POST";
string ext = "pjpeg";
try
{
ext = new Regex(@"^.+?\.(\w+)$").Match(filename).Groups[1].Value;
}
catch
{}
string sBoundary = DateTime.Now.Ticks.ToString("x");
ua.ContentType = "multipart/form-data; boundary=" + sBoundary;
string sPostMultiString = "";
sPostMultiString += MultiFormData("method", "post", sBoundary);
sPostMultiString += MultiFormData("key", this.key, sBoundary);
sPostMultiString += MultiFormData("soft_id", "65", sBoundary);
sPostMultiString += MultiFormData("file", filename, sBoundary);
sPostMultiString += MultiFormData("phrase", Convert.ToString(phrase), sBoundary);
sPostMultiString += MultiFormData("regsense", Convert.ToString(regsense), sBoundary);
sPostMultiString += MultiFormData("numeric", Convert.ToString(numeric), sBoundary);
sPostMultiString += MultiFormData("calc", Convert.ToString(calc), sBoundary);
sPostMultiString += MultiFormData("min_len", Convert.ToString(min_len), sBoundary);
sPostMultiString += MultiFormData("max_len", Convert.ToString(max_len), sBoundary);
string sFileContent = "";
using (BinaryReader br = new BinaryReader(File.Open(filename, FileMode.Open), Encoding.Default))
{
byte[] ba = new byte[32768];
int pos = 0;
byte b;
while (true)
{
try
{ b = br.ReadByte(); }
catch (EndOfStreamException ex)
{
break;
}
ba[pos] = b;
pos++;
}
byte[] ba2 = new byte[pos];
for (int k = 0; k < pos; k++)
{
ba2[k] = ba[k];
}
sFileContent = Encoding.Default.GetString(ba2);
}
sPostMultiString += MultiFormDataFile("file", sFileContent, filename, "image/" + ext, sBoundary);
sPostMultiString += "--" + sBoundary + "--\r\n\r\n";
byte[] byteArray = Encoding.Default.GetBytes(sPostMultiString);
ua.ContentLength = byteArray.Length;
ua.GetRequestStream().Write(byteArray, 0, byteArray.Length);
try
{
HttpWebResponse myHttpWebResponse = (HttpWebResponse)ua.GetResponse();
StreamReader myStreamReadermy = new StreamReader(myHttpWebResponse.GetResponseStream() , Encoding.GetEncoding(1251));
result_page = myStreamReadermy.ReadToEnd();
//result_headers = myHttpWebResponse.Headers.ToString();
string[] result = result_page.Split(new char[1] { '|' });
last_cap_id = result[1];
dbg("req " + last_cap_id + ": uploaded!");
while (1 == 1)
{
string captcha = get(last_cap_id);
if (captcha == "")
{
Thread.Sleep(2000);
}
else
{
return captcha;
}
}
}
catch (WebException ex)
{
//Console.WriteLine(ex);
return "";
}
}
public string get(string cap_id)
{
if (this.req("http://" + host + "/res.php?key=" + key + "&action=get&id=" + cap_id + "&"))
{
dbg("get " + cap_id + " : " + result_page);
try
{
string[] result = result_page.Split(new char[1] { '|' });
dbg("recorgenized " + cap_id + " : " + result[1]);
return result[1];
}
catch
{
return "";
}
}
return "";
}
public string get_balance()
{
string key = this.key;
return get_balance(key);
}
public string get_balance(string key)
{
if (this.req("http://" + host + "/res.php?key=" + key + "&action=getbalance"))
{
dbg("get_balance: " + result_page);
return result_page;
}
return "-1";
}
public bool reportbad()
{
return reportbad(last_cap_id);
}
public bool reportbad(string cap_id)
{
if (this.req("http://" + host + "/res.php?key=" + key + "&action=reportbad&id=" + cap_id))
{
dbg("reportbad " + cap_id + ": " + result_page);
if (result_page.IndexOf("ERROR") >= 0)
{
return false;
}
return true;
}
return false;
}
public void dbg(string s)
{
if (this.debug == true)
{
Console.WriteLine("AC: " + s);
}
}
private bool req(string url)
{
ua = browser(url);
ua.Method = "GET";
ua.KeepAlive = true;
try
{
HttpWebResponse myHttpWebResponse = (HttpWebResponse)ua.GetResponse();
StreamReader myStreamReadermy = new StreamReader(myHttpWebResponse.GetResponseStream() , Encoding.GetEncoding(1251));
result_page = myStreamReadermy.ReadToEnd();
result_headers = myHttpWebResponse.Headers.ToString();
return true;
}
catch (WebException ex)
{
//Console.WriteLine(ex);
return false;
}
}
private HttpWebRequest browser(string url)
{
HttpWebRequest ua = (HttpWebRequest)System.Net.WebRequest.Create(url);
if (use_proxy())
{
WebProxy myProxy = new WebProxy(proxy_host, proxy_port);
myProxy.Credentials = new NetworkCredential(proxy_username, proxy_password);
ua.Proxy = myProxy;
}
ua.AllowAutoRedirect = true;
ua.Timeout = 10000;
ua.UserAgent = "C# Anticaptcha Class (elw)";
ua.Accept = "*/*";
return ua;
}
private bool use_proxy()
{
if (String.IsNullOrEmpty(proxy))
{
return false;
}
string[] aProxy = proxy.Split(new char[1] { ':' });
proxy_host = aProxy[0];
proxy_port = int.Parse(aProxy[1]);
return true;
}
public static string MultiFormData(string Key, string Value, string Boundary)
{
string output = "--" + Boundary + "\r\n"; output += "Content-Disposition: form-data; name=\"" + Key + "\"\r\n\r\n";
output += Value + "\r\n";
return output;
}
public static string MultiFormDataFile(string Key, string Value, string FileName, string FileType, string Boundary)
{
string output = "--" + Boundary + "\r\n";
output += "Content-Disposition: form-data; name=\"" + Key + "\"; filename=\"" + FileName + "\"\r\n";
output += "Content-Type: " + FileType + " \r\n\r\n";
output += Value + "\r\n";
return output;
}
}
/* пример использования /*
using System.Threading;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;
..............
anticaptcha ac = new anticaptcha();
ac.host = "antigate.com";
ac.key = "dd5c63473..ваш.ключ..b67d96b3754a";
// проверяем баланс
string balance = ac.get_balance();
Console.WriteLine("current balance = " + balance);
// отправляем капчу
string cap = ac.rec("some_captcha.jpg");
// можем отправить жалобу, если капча роспозналась неверно
ac.reportbad();
..............
/* */
Далее мы запускаем http analyzer и смотрим на то, что и каким образом принимается qip.ru для регистрации
NO. Starred OffSet Timeline Duration(s) Method Result Received Type URL RedirectURL
50 False + 0,078 0,595 s POST 200 20,34 K text/html http://www.qip.ru/reg/register
51 False + 0,781 0,501 s GET 200 1,41 K text/javascript http://api.recaptcha.net/challenge?k=6LeUWwgAAAAAAMHS93Je_FMHwGu30Z3T-hrqsCiO
52 False + 0,797 0,204 s GET 407 4,47 K text/html http://count.rbc.ru/p787.gif?r=http%3A//www.qip.ru/reg/register&width=1229&height=983&hash=&rf=http%3A//www.qip.ru/reg/register&rn=0.9010899220605391
53 False + 0,812 0,205 s GET 407 4,47 K text/html http://www.tns-counter.ru/V13a***R%3Ehttp://www.qip.ru/reg/register*rbc_ru/ru/UTF-8/tmsec=rbc_qip/
56 False + 1,016 0,001 s GET 407 560 text/html http://count.rbc.ru/p787.gif?r=http%3A//www.qip.ru/reg/register&width=1229&height=983&hash=&rf=http%3A//www.qip.ru/reg/register&rn=0.9010899220605391
57 False + 1,031 0,001 s GET 407 560 text/html http://www.tns-counter.ru/V13a***R%3Ehttp://www.qip.ru/reg/register*rbc_ru/ru/UTF-8/tmsec=rbc_qip/
58 False + 1,031 0,017 s GET 200 352 image/gif http://count.rbc.ru/p787.gif?r=http%3A//www.qip.ru/reg/register&width=1229&height=983&hash=&rf=http%3A//www.qip.ru/reg/register&rn=0.9010899220605391
59 False + 1,047 0,032 s GET 200 494 image/gif http://www.tns-counter.ru/V13a***R%3Ehttp://www.qip.ru/reg/register*rbc_ru/ru/UTF-8/tmsec=rbc_qip/
60 False + 0,828 0,282 s GET 407 4,47 K text/html http://counter.yadro.ru/hit;start-qip-ru?rhttp%3A//www.qip.ru/reg/register;s1229*983*32;uhttp%3A//www.qip.ru/reg/register;0.8095833998461599
61 False + 1,125 0,017 s GET 200 319 image/gif http://counter.yadro.ru/hit;start-qip-ru?rhttp%3A//www.qip.ru/reg/register;s1229*983*32;uhttp%3A//www.qip.ru/reg/register;0.8095833998461599
62 False + 1,312 0,330 s GET 200 657 text/javascript http://www.google.com/recaptcha/api/challenge?k=6LeUWwgAAAAAAMHS93Je_FMHwGu30Z3T-hrqsCiO&darklaunch=1
63 False + 1,328 0,329 s GET 407 4,47 K text/html http://api.recaptcha.net/image?c=02J47UfMZX6cCuvACiI6SfKDWh4wWwrLm6MGvOWtk_ qSs2i0sxYHTPESrR73yZ70m7zcUYsxgSN0b6LKKu3PsCbcuQ7j 39YETh-8Cc2CY9d4S-MhroSbHiLEs1DFjQ1PmC_iP6WUodiFJ6iUVJRW_UmqCbcRI8i7 VF1vWzgc3mCpAgAqZxbh97zSQR6EBWXtUWgRQ-PesnrZy5Gr21by4jzpQRsASE6oKkDajIT3hlT2o1pETFKYjmBX tQLcG_dXby-yBWF5hXfQnwKvV5cyLJDBNcrxIB
64 False + 1,328 0,032 s GET 200 278 image/gif http://counter.rambler.ru/top100.cnt?1185528
65 False + 1,578 0,048 s GET 200 396 image/gif http://counter.yadro.ru/logo?26.1
66 False + 1,672 0,532 s GET 200 3,25 K image/jpeg http://api.recaptcha.net/image?c=02J47UfMZX6cCuvACiI6SfKDWh4wWwrLm6MGvOWtk_ qSs2i0sxYHTPESrR73yZ70m7zcUYsxgSN0b6LKKu3PsCbcuQ7j 39YETh-8Cc2CY9d4S-MhroSbHiLEs1DFjQ1PmC_iP6WUodiFJ6iUVJRW_UmqCbcRI8i7 VF1vWzgc3mCpAgAqZxbh97zSQR6EBWXtUWgRQ-PesnrZy5Gr21by4jzpQRsASE6oKkDajIT3hlT2o1pETFKYjmBX tQLcG_dXby-yBWF5hXfQnwKvV5cyLJDBNcrxIB
67 False + 1,625 0,329 s GET 407 4,47 K text/html http://rbcgaru.hit.gemius.pl/_1270623070349/rexdot.gif?l=30&id=AjtLm6urvIF2uTw7.v8m36Pe33MGxnsw3wib9RJAMRP.R7&fr=1&fv=WIN%2010%2C0%2C45%2C2&tz=-240&href=http%3A//www.qip.ru/reg/register&ref=http%3A//www.qip.ru/reg/register&screen=1229x983&col=32
70 False + 1,734 0,236 s GET 407 4,47 K text/html http://www.google.com/recaptcha/api/image?c=03AHJ_VusxISEkjwxVAPKICmaPBPTTxmkYI9ZWLen9 uOQUMX-uwn0kJiY1Ub3wUO7zPYoXGLBLYOxf5-aGp-lb9ErW69GEbbGkjx6Y0zRErTJKkbieEgTyc_IVybSZXyaP39Vr Ux0WPxk_8INAvYeXpw9uhjt7ynBcAw
73 False + 1,969 0,032 s GET 200 516 image/gif http://rbcgaru.hit.gemius.pl/_1270623070349/rexdot.gif?l=30&id=AjtLm6urvIF2uTw7.v8m36Pe33MGxnsw3wib9RJAMRP.R7&fr=1&fv=WIN%2010%2C0%2C45%2C2&tz=-240&href=http%3A//www.qip.ru/reg/register&ref=http%3A//www.qip.ru/reg/register&screen=1229x983&col=32
74 False + 1,984 0,033 s GET 407 560 text/html http://www.google.com/recaptcha/api/image?c=03AHJ_VusxISEkjwxVAPKICmaPBPTTxmkYI9ZWLen9 uOQUMX-uwn0kJiY1Ub3wUO7zPYoXGLBLYOxf5-aGp-lb9ErW69GEbbGkjx6Y0zRErTJKkbieEgTyc_IVybSZXyaP39Vr Ux0WPxk_8INAvYeXpw9uhjt7ynBcAw
75 False + 2,016 0,188 s GET 200 3,26 K image/jpeg http://www.google.com/recaptcha/api/image?c=03AHJ_VusxISEkjwxVAPKICmaPBPTTxmkYI9ZWLen9 uOQUMX-uwn0kJiY1Ub3wUO7zPYoXGLBLYOxf5-aGp-lb9ErW69GEbbGkjx6Y0zRErTJKkbieEgTyc_IVybSZXyaP39Vr Ux0WPxk_8INAvYeXpw9uhjt7ynBcAw
И что уходит после нажатия кнопки «регистрация»
Parameter Name Value
username asdasdasd
reg_host 0
pwd asdasdasd
pwd2 asdasdasd
email asdasd@asd.ru
quest 0
reg_quest
reg_answer
last_name
first_name
middle_name
bday 0
bmonth 0
byear 0
city
recaptcha_challenge_field 02NblAb1JGCfoIu1AhL-aqceKDN61Q9_rAeEFSufpyzd910MuEgb8qkMaNmcsFGiZSkYqA vYr4e1JlP3-IVyymHH940SoBuIOBa6Fzpjw5ZMQ7E8pNQy0tFvOxMozVPBFQx qwxOxWFu-_n27cLcWn3yAh1J09wJfyPWgzexcm80WjsD-nmRGZsM1s_XZTNSy5JosHTtgIvVWUFHiPW3fYh3NVwUu2C3Rhs yGlzU6lI-mTpUZ6ZxdtPIjnJ5Qe0WpfBuXzGl4YC0VMoChh913dr31n_A_E B
recaptcha_response_field presbrey nations
Теперь понятно что нужно отправить поэтому приступим к коду.
string sHTML = "";
string recaptcha_challenge_field = "";
string cap = "";
HTTPClient client = new HTTPClient("session");
HttpWebResponse httpWebResponse = client.Request("http://www.qip.ru/reg/register",false);
if (httpWebResponse != null && httpWebResponse.StatusCode == HttpStatusCode.OK)
{
Stream stream = httpWebResponse.GetResponseStream();
using (StreamReader reader = new StreamReader(stream, System.Text.Encoding.UTF8))
{
sHTML = reader.ReadToEnd();
}
// Получаем ID Капчи
httpWebResponse = client.Request("http://api.recaptcha.net/noscript?k=6LeUWwgAAAAAAMHS93Je_FMHwGu30Z3T-hrqsCiO");
if (httpWebResponse != null && httpWebResponse.StatusCode == HttpStatusCode.OK)
{
stream = httpWebResponse.GetResponseStream();
using (StreamReader reader = new StreamReader(stream, System.Text.Encoding.UTF8))
{
sHTML = reader.ReadToEnd();
}
string pattern = "(\\s)";
string capcha_id = @"(?<=recaptcha_challenge_field"+'"'+" value="+'"'+")(\\S+)(?="+'"'+")";
Regex rx = new Regex(capcha_id);
recaptcha_challenge_field = rx.Match(sHTML).Value;
}
// Получаем Картинку
httpWebResponse = client.Request("http://api.recaptcha.net/image?c=" + recaptcha_challenge_field);
if (httpWebResponse != null && httpWebResponse.StatusCode == HttpStatusCode.OK)
{
stream = httpWebResponse.GetResponseStream();
Bitmap b = new Bitmap(stream);
b.Save("some_captcha.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
using (StreamReader reader = new StreamReader(stream, System.Text.Encoding.UTF8))
{
sHTML = reader.ReadToEnd();
}
anticaptcha ac = new anticaptcha();
ac.host = "antigate.com";
ac.key = "ваш ключ на antigate";
ac.proxy = "x.x.x.x:3128";
ac.proxy_username = "username";
ac.proxy_password = "password";
//ac.
// проверяем баланс
string balance = ac.get_balance();
CultureInfo ciClone = null;
ciClone = (CultureInfo)CultureInfo.InvariantCulture.Clone();
ciClone.NumberFormat.NumberDecimalSeparator = ".";
ciClone.NumberFormat.NumberGroupSeparator = ",";
if(Double.Parse(balance,ciClone) > 0){
// отправляем капчу
cap = ac.rec("some_captcha.jpg");
}
// можем отправить жалобу, если капча роспозналась неверно
//ac.reportbad();
}
Regex rx2 = new Regex("(\\s)");
cap = rx2.Replace(cap, "+");
string post_reg = @"bday=0&"
+ "bmonth=0&"
+ "byear=0&"
+ "city=&"
+ "email=asdasdasd@asd.ru&"
+ "first_name=&"
+ "last_name&"
+ "middle_name&"
+ "pwd=asdasdasd&"
+ "pwd2=asdasdasd&"
+ "quest=0&"
+ "recaptcha_challenge_field="+recaptcha_challenge_field+"&"
+ "recaptcha_response_field="+cap+"&"
+ "reg_answer=&"
+ "reg_host=0&"
+ "reg_quest=&"
+ "username=asdasdasd1234";
httpWebResponse.Close();
httpWebResponse = client.Request_Post("http://www.qip.ru/reg/register", post_reg);
if (httpWebResponse != null && httpWebResponse.StatusCode == HttpStatusCode.OK)
{
stream = httpWebResponse.GetResponseStream();
using (StreamReader reader = new StreamReader(stream, System.Text.Encoding.UTF8))
{
sHTML = reader.ReadToEnd();
}
}
}
Вообщем то все.
Осталось добавить многопоточность и всем удачи :D
Замечания и предложения приветствуются. :)
Хочу поделиться радостью :p
Изучая C#, решил начать с простых вещей, так что первая статья в этом направлении будет про автоматическую регистрацию почтового ящика на qip.ru.
Собственно, как оказалось, все очень даже просто.
Первым делом необходимо создать класс для работы с http.
Класс нужен для того чтобы облегчить нам отправку и получение http запросов с сохранностью cookie.
public class HTTPClient
{
private CookieCollection Cooks = new CookieCollection();
public HTTPClient(string session_cookiename)
{
}
public void ClearCookie()
{
}
public HttpWebResponse Request(string sUrl)
{
return Request(sUrl, true);
}
public HttpWebResponse Request_Post(string path, string post_body)
{
return Request_Post(path, post_body, true);
}
public HttpWebResponse Request_Post(string path, string post_body, bool bAutoRedirect)
{
try
{
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(path);
httpWebRequest.Proxy = new WebProxy("x.x.x.x", 3128);
httpWebRequest.Proxy.Credentials = new NetworkCredential("username", "password","domain");
httpWebRequest.AllowAutoRedirect = bAutoRedirect;
httpWebRequest.CookieContainer = new CookieContainer();
if (Cooks != null)
{
httpWebRequest.CookieContainer.Add(Cooks);
}
httpWebRequest.Method = "POST";
httpWebRequest.ContentType = "application/x-www-form-urlencoded";
byte[] ByteQuery = System.Text.Encoding.ASCII.GetBytes(post_body);
httpWebRequest.ContentLength = ByteQuery.Length;
Stream QueryStream = httpWebRequest.GetRequestStream();
QueryStream.Write(ByteQuery, 0, ByteQuery.Length);
QueryStream.Close();
HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
httpWebResponse.Cookies = httpWebRequest.CookieContainer.GetCookies(httpWebR equest.RequestUri);
if (httpWebResponse.Cookies != null)
{
Cooks.Add(httpWebResponse.Cookies);
}
return httpWebResponse;
}
catch (WebException ex)
{
return ex.Response as HttpWebResponse;
}
}
public HttpWebResponse Request(string sUrl, bool bAutoRedirect)
{
try
{
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(sUrl);
httpWebRequest.Proxy = new WebProxy("x.x.x.x", 3128);
httpWebRequest.Proxy.Credentials = new NetworkCredential("username", "password", "domain");
httpWebRequest.AllowAutoRedirect = bAutoRedirect;
httpWebRequest.CookieContainer = new CookieContainer();
if (Cooks != null)
{
httpWebRequest.CookieContainer.Add(Cooks);
}
HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
httpWebResponse.Cookies = httpWebRequest.CookieContainer.GetCookies(httpWebR equest.RequestUri);
if (httpWebResponse.Cookies != null)
{
Cooks.Add(httpWebResponse.Cookies);
}
return httpWebResponse;
}
catch (WebException ex)
{
return ex.Response as HttpWebResponse;
}
}
}
Класс содержит CookieCollection и 2 функции возвращающие HttpWebResponse:
Одна с POST запросом, вторая без.
Так же для автоматического распознования понадобится класс работы с antigate. Отдельное спасибо elw.
class anticaptcha
{
public bool debug = false;
public string host = "antigate.com";
public string key;
public string proxy = "";
public string proxy_username = "";
public string proxy_password = "";
public int phrase = 0; // у капчи 2-4 слова = 1
public int regsense = 0; // текст капчи чувствителен к регистру = 1
public int numeric = 0; // капча состоит только с цифр = 1,
// на капче нет цифр = 2
public int calc = 0; // цифры на капче должны быть сплюсованы = 1
public int min_len = 0; // минимальная длину текста капчи
public int max_len = 0; // максимальная длина текста капчи
private string proxy_host = "";
private int proxy_port;
private string result_headers;
private string result_page;
private HttpWebRequest ua;
private string last_cap_id;
public string rec(string filename)
{
ua = browser("http://" + host + "/in.php");
ua.Method = "POST";
string ext = "pjpeg";
try
{
ext = new Regex(@"^.+?\.(\w+)$").Match(filename).Groups[1].Value;
}
catch
{}
string sBoundary = DateTime.Now.Ticks.ToString("x");
ua.ContentType = "multipart/form-data; boundary=" + sBoundary;
string sPostMultiString = "";
sPostMultiString += MultiFormData("method", "post", sBoundary);
sPostMultiString += MultiFormData("key", this.key, sBoundary);
sPostMultiString += MultiFormData("soft_id", "65", sBoundary);
sPostMultiString += MultiFormData("file", filename, sBoundary);
sPostMultiString += MultiFormData("phrase", Convert.ToString(phrase), sBoundary);
sPostMultiString += MultiFormData("regsense", Convert.ToString(regsense), sBoundary);
sPostMultiString += MultiFormData("numeric", Convert.ToString(numeric), sBoundary);
sPostMultiString += MultiFormData("calc", Convert.ToString(calc), sBoundary);
sPostMultiString += MultiFormData("min_len", Convert.ToString(min_len), sBoundary);
sPostMultiString += MultiFormData("max_len", Convert.ToString(max_len), sBoundary);
string sFileContent = "";
using (BinaryReader br = new BinaryReader(File.Open(filename, FileMode.Open), Encoding.Default))
{
byte[] ba = new byte[32768];
int pos = 0;
byte b;
while (true)
{
try
{ b = br.ReadByte(); }
catch (EndOfStreamException ex)
{
break;
}
ba[pos] = b;
pos++;
}
byte[] ba2 = new byte[pos];
for (int k = 0; k < pos; k++)
{
ba2[k] = ba[k];
}
sFileContent = Encoding.Default.GetString(ba2);
}
sPostMultiString += MultiFormDataFile("file", sFileContent, filename, "image/" + ext, sBoundary);
sPostMultiString += "--" + sBoundary + "--\r\n\r\n";
byte[] byteArray = Encoding.Default.GetBytes(sPostMultiString);
ua.ContentLength = byteArray.Length;
ua.GetRequestStream().Write(byteArray, 0, byteArray.Length);
try
{
HttpWebResponse myHttpWebResponse = (HttpWebResponse)ua.GetResponse();
StreamReader myStreamReadermy = new StreamReader(myHttpWebResponse.GetResponseStream() , Encoding.GetEncoding(1251));
result_page = myStreamReadermy.ReadToEnd();
//result_headers = myHttpWebResponse.Headers.ToString();
string[] result = result_page.Split(new char[1] { '|' });
last_cap_id = result[1];
dbg("req " + last_cap_id + ": uploaded!");
while (1 == 1)
{
string captcha = get(last_cap_id);
if (captcha == "")
{
Thread.Sleep(2000);
}
else
{
return captcha;
}
}
}
catch (WebException ex)
{
//Console.WriteLine(ex);
return "";
}
}
public string get(string cap_id)
{
if (this.req("http://" + host + "/res.php?key=" + key + "&action=get&id=" + cap_id + "&"))
{
dbg("get " + cap_id + " : " + result_page);
try
{
string[] result = result_page.Split(new char[1] { '|' });
dbg("recorgenized " + cap_id + " : " + result[1]);
return result[1];
}
catch
{
return "";
}
}
return "";
}
public string get_balance()
{
string key = this.key;
return get_balance(key);
}
public string get_balance(string key)
{
if (this.req("http://" + host + "/res.php?key=" + key + "&action=getbalance"))
{
dbg("get_balance: " + result_page);
return result_page;
}
return "-1";
}
public bool reportbad()
{
return reportbad(last_cap_id);
}
public bool reportbad(string cap_id)
{
if (this.req("http://" + host + "/res.php?key=" + key + "&action=reportbad&id=" + cap_id))
{
dbg("reportbad " + cap_id + ": " + result_page);
if (result_page.IndexOf("ERROR") >= 0)
{
return false;
}
return true;
}
return false;
}
public void dbg(string s)
{
if (this.debug == true)
{
Console.WriteLine("AC: " + s);
}
}
private bool req(string url)
{
ua = browser(url);
ua.Method = "GET";
ua.KeepAlive = true;
try
{
HttpWebResponse myHttpWebResponse = (HttpWebResponse)ua.GetResponse();
StreamReader myStreamReadermy = new StreamReader(myHttpWebResponse.GetResponseStream() , Encoding.GetEncoding(1251));
result_page = myStreamReadermy.ReadToEnd();
result_headers = myHttpWebResponse.Headers.ToString();
return true;
}
catch (WebException ex)
{
//Console.WriteLine(ex);
return false;
}
}
private HttpWebRequest browser(string url)
{
HttpWebRequest ua = (HttpWebRequest)System.Net.WebRequest.Create(url);
if (use_proxy())
{
WebProxy myProxy = new WebProxy(proxy_host, proxy_port);
myProxy.Credentials = new NetworkCredential(proxy_username, proxy_password);
ua.Proxy = myProxy;
}
ua.AllowAutoRedirect = true;
ua.Timeout = 10000;
ua.UserAgent = "C# Anticaptcha Class (elw)";
ua.Accept = "*/*";
return ua;
}
private bool use_proxy()
{
if (String.IsNullOrEmpty(proxy))
{
return false;
}
string[] aProxy = proxy.Split(new char[1] { ':' });
proxy_host = aProxy[0];
proxy_port = int.Parse(aProxy[1]);
return true;
}
public static string MultiFormData(string Key, string Value, string Boundary)
{
string output = "--" + Boundary + "\r\n"; output += "Content-Disposition: form-data; name=\"" + Key + "\"\r\n\r\n";
output += Value + "\r\n";
return output;
}
public static string MultiFormDataFile(string Key, string Value, string FileName, string FileType, string Boundary)
{
string output = "--" + Boundary + "\r\n";
output += "Content-Disposition: form-data; name=\"" + Key + "\"; filename=\"" + FileName + "\"\r\n";
output += "Content-Type: " + FileType + " \r\n\r\n";
output += Value + "\r\n";
return output;
}
}
/* пример использования /*
using System.Threading;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;
..............
anticaptcha ac = new anticaptcha();
ac.host = "antigate.com";
ac.key = "dd5c63473..ваш.ключ..b67d96b3754a";
// проверяем баланс
string balance = ac.get_balance();
Console.WriteLine("current balance = " + balance);
// отправляем капчу
string cap = ac.rec("some_captcha.jpg");
// можем отправить жалобу, если капча роспозналась неверно
ac.reportbad();
..............
/* */
Далее мы запускаем http analyzer и смотрим на то, что и каким образом принимается qip.ru для регистрации
NO. Starred OffSet Timeline Duration(s) Method Result Received Type URL RedirectURL
50 False + 0,078 0,595 s POST 200 20,34 K text/html http://www.qip.ru/reg/register
51 False + 0,781 0,501 s GET 200 1,41 K text/javascript http://api.recaptcha.net/challenge?k=6LeUWwgAAAAAAMHS93Je_FMHwGu30Z3T-hrqsCiO
52 False + 0,797 0,204 s GET 407 4,47 K text/html http://count.rbc.ru/p787.gif?r=http%3A//www.qip.ru/reg/register&width=1229&height=983&hash=&rf=http%3A//www.qip.ru/reg/register&rn=0.9010899220605391
53 False + 0,812 0,205 s GET 407 4,47 K text/html http://www.tns-counter.ru/V13a***R%3Ehttp://www.qip.ru/reg/register*rbc_ru/ru/UTF-8/tmsec=rbc_qip/
56 False + 1,016 0,001 s GET 407 560 text/html http://count.rbc.ru/p787.gif?r=http%3A//www.qip.ru/reg/register&width=1229&height=983&hash=&rf=http%3A//www.qip.ru/reg/register&rn=0.9010899220605391
57 False + 1,031 0,001 s GET 407 560 text/html http://www.tns-counter.ru/V13a***R%3Ehttp://www.qip.ru/reg/register*rbc_ru/ru/UTF-8/tmsec=rbc_qip/
58 False + 1,031 0,017 s GET 200 352 image/gif http://count.rbc.ru/p787.gif?r=http%3A//www.qip.ru/reg/register&width=1229&height=983&hash=&rf=http%3A//www.qip.ru/reg/register&rn=0.9010899220605391
59 False + 1,047 0,032 s GET 200 494 image/gif http://www.tns-counter.ru/V13a***R%3Ehttp://www.qip.ru/reg/register*rbc_ru/ru/UTF-8/tmsec=rbc_qip/
60 False + 0,828 0,282 s GET 407 4,47 K text/html http://counter.yadro.ru/hit;start-qip-ru?rhttp%3A//www.qip.ru/reg/register;s1229*983*32;uhttp%3A//www.qip.ru/reg/register;0.8095833998461599
61 False + 1,125 0,017 s GET 200 319 image/gif http://counter.yadro.ru/hit;start-qip-ru?rhttp%3A//www.qip.ru/reg/register;s1229*983*32;uhttp%3A//www.qip.ru/reg/register;0.8095833998461599
62 False + 1,312 0,330 s GET 200 657 text/javascript http://www.google.com/recaptcha/api/challenge?k=6LeUWwgAAAAAAMHS93Je_FMHwGu30Z3T-hrqsCiO&darklaunch=1
63 False + 1,328 0,329 s GET 407 4,47 K text/html http://api.recaptcha.net/image?c=02J47UfMZX6cCuvACiI6SfKDWh4wWwrLm6MGvOWtk_ qSs2i0sxYHTPESrR73yZ70m7zcUYsxgSN0b6LKKu3PsCbcuQ7j 39YETh-8Cc2CY9d4S-MhroSbHiLEs1DFjQ1PmC_iP6WUodiFJ6iUVJRW_UmqCbcRI8i7 VF1vWzgc3mCpAgAqZxbh97zSQR6EBWXtUWgRQ-PesnrZy5Gr21by4jzpQRsASE6oKkDajIT3hlT2o1pETFKYjmBX tQLcG_dXby-yBWF5hXfQnwKvV5cyLJDBNcrxIB
64 False + 1,328 0,032 s GET 200 278 image/gif http://counter.rambler.ru/top100.cnt?1185528
65 False + 1,578 0,048 s GET 200 396 image/gif http://counter.yadro.ru/logo?26.1
66 False + 1,672 0,532 s GET 200 3,25 K image/jpeg http://api.recaptcha.net/image?c=02J47UfMZX6cCuvACiI6SfKDWh4wWwrLm6MGvOWtk_ qSs2i0sxYHTPESrR73yZ70m7zcUYsxgSN0b6LKKu3PsCbcuQ7j 39YETh-8Cc2CY9d4S-MhroSbHiLEs1DFjQ1PmC_iP6WUodiFJ6iUVJRW_UmqCbcRI8i7 VF1vWzgc3mCpAgAqZxbh97zSQR6EBWXtUWgRQ-PesnrZy5Gr21by4jzpQRsASE6oKkDajIT3hlT2o1pETFKYjmBX tQLcG_dXby-yBWF5hXfQnwKvV5cyLJDBNcrxIB
67 False + 1,625 0,329 s GET 407 4,47 K text/html http://rbcgaru.hit.gemius.pl/_1270623070349/rexdot.gif?l=30&id=AjtLm6urvIF2uTw7.v8m36Pe33MGxnsw3wib9RJAMRP.R7&fr=1&fv=WIN%2010%2C0%2C45%2C2&tz=-240&href=http%3A//www.qip.ru/reg/register&ref=http%3A//www.qip.ru/reg/register&screen=1229x983&col=32
70 False + 1,734 0,236 s GET 407 4,47 K text/html http://www.google.com/recaptcha/api/image?c=03AHJ_VusxISEkjwxVAPKICmaPBPTTxmkYI9ZWLen9 uOQUMX-uwn0kJiY1Ub3wUO7zPYoXGLBLYOxf5-aGp-lb9ErW69GEbbGkjx6Y0zRErTJKkbieEgTyc_IVybSZXyaP39Vr Ux0WPxk_8INAvYeXpw9uhjt7ynBcAw
73 False + 1,969 0,032 s GET 200 516 image/gif http://rbcgaru.hit.gemius.pl/_1270623070349/rexdot.gif?l=30&id=AjtLm6urvIF2uTw7.v8m36Pe33MGxnsw3wib9RJAMRP.R7&fr=1&fv=WIN%2010%2C0%2C45%2C2&tz=-240&href=http%3A//www.qip.ru/reg/register&ref=http%3A//www.qip.ru/reg/register&screen=1229x983&col=32
74 False + 1,984 0,033 s GET 407 560 text/html http://www.google.com/recaptcha/api/image?c=03AHJ_VusxISEkjwxVAPKICmaPBPTTxmkYI9ZWLen9 uOQUMX-uwn0kJiY1Ub3wUO7zPYoXGLBLYOxf5-aGp-lb9ErW69GEbbGkjx6Y0zRErTJKkbieEgTyc_IVybSZXyaP39Vr Ux0WPxk_8INAvYeXpw9uhjt7ynBcAw
75 False + 2,016 0,188 s GET 200 3,26 K image/jpeg http://www.google.com/recaptcha/api/image?c=03AHJ_VusxISEkjwxVAPKICmaPBPTTxmkYI9ZWLen9 uOQUMX-uwn0kJiY1Ub3wUO7zPYoXGLBLYOxf5-aGp-lb9ErW69GEbbGkjx6Y0zRErTJKkbieEgTyc_IVybSZXyaP39Vr Ux0WPxk_8INAvYeXpw9uhjt7ynBcAw
И что уходит после нажатия кнопки «регистрация»
Parameter Name Value
username asdasdasd
reg_host 0
pwd asdasdasd
pwd2 asdasdasd
email asdasd@asd.ru
quest 0
reg_quest
reg_answer
last_name
first_name
middle_name
bday 0
bmonth 0
byear 0
city
recaptcha_challenge_field 02NblAb1JGCfoIu1AhL-aqceKDN61Q9_rAeEFSufpyzd910MuEgb8qkMaNmcsFGiZSkYqA vYr4e1JlP3-IVyymHH940SoBuIOBa6Fzpjw5ZMQ7E8pNQy0tFvOxMozVPBFQx qwxOxWFu-_n27cLcWn3yAh1J09wJfyPWgzexcm80WjsD-nmRGZsM1s_XZTNSy5JosHTtgIvVWUFHiPW3fYh3NVwUu2C3Rhs yGlzU6lI-mTpUZ6ZxdtPIjnJ5Qe0WpfBuXzGl4YC0VMoChh913dr31n_A_E B
recaptcha_response_field presbrey nations
Теперь понятно что нужно отправить поэтому приступим к коду.
string sHTML = "";
string recaptcha_challenge_field = "";
string cap = "";
HTTPClient client = new HTTPClient("session");
HttpWebResponse httpWebResponse = client.Request("http://www.qip.ru/reg/register",false);
if (httpWebResponse != null && httpWebResponse.StatusCode == HttpStatusCode.OK)
{
Stream stream = httpWebResponse.GetResponseStream();
using (StreamReader reader = new StreamReader(stream, System.Text.Encoding.UTF8))
{
sHTML = reader.ReadToEnd();
}
// Получаем ID Капчи
httpWebResponse = client.Request("http://api.recaptcha.net/noscript?k=6LeUWwgAAAAAAMHS93Je_FMHwGu30Z3T-hrqsCiO");
if (httpWebResponse != null && httpWebResponse.StatusCode == HttpStatusCode.OK)
{
stream = httpWebResponse.GetResponseStream();
using (StreamReader reader = new StreamReader(stream, System.Text.Encoding.UTF8))
{
sHTML = reader.ReadToEnd();
}
string pattern = "(\\s)";
string capcha_id = @"(?<=recaptcha_challenge_field"+'"'+" value="+'"'+")(\\S+)(?="+'"'+")";
Regex rx = new Regex(capcha_id);
recaptcha_challenge_field = rx.Match(sHTML).Value;
}
// Получаем Картинку
httpWebResponse = client.Request("http://api.recaptcha.net/image?c=" + recaptcha_challenge_field);
if (httpWebResponse != null && httpWebResponse.StatusCode == HttpStatusCode.OK)
{
stream = httpWebResponse.GetResponseStream();
Bitmap b = new Bitmap(stream);
b.Save("some_captcha.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
using (StreamReader reader = new StreamReader(stream, System.Text.Encoding.UTF8))
{
sHTML = reader.ReadToEnd();
}
anticaptcha ac = new anticaptcha();
ac.host = "antigate.com";
ac.key = "ваш ключ на antigate";
ac.proxy = "x.x.x.x:3128";
ac.proxy_username = "username";
ac.proxy_password = "password";
//ac.
// проверяем баланс
string balance = ac.get_balance();
CultureInfo ciClone = null;
ciClone = (CultureInfo)CultureInfo.InvariantCulture.Clone();
ciClone.NumberFormat.NumberDecimalSeparator = ".";
ciClone.NumberFormat.NumberGroupSeparator = ",";
if(Double.Parse(balance,ciClone) > 0){
// отправляем капчу
cap = ac.rec("some_captcha.jpg");
}
// можем отправить жалобу, если капча роспозналась неверно
//ac.reportbad();
}
Regex rx2 = new Regex("(\\s)");
cap = rx2.Replace(cap, "+");
string post_reg = @"bday=0&"
+ "bmonth=0&"
+ "byear=0&"
+ "city=&"
+ "email=asdasdasd@asd.ru&"
+ "first_name=&"
+ "last_name&"
+ "middle_name&"
+ "pwd=asdasdasd&"
+ "pwd2=asdasdasd&"
+ "quest=0&"
+ "recaptcha_challenge_field="+recaptcha_challenge_field+"&"
+ "recaptcha_response_field="+cap+"&"
+ "reg_answer=&"
+ "reg_host=0&"
+ "reg_quest=&"
+ "username=asdasdasd1234";
httpWebResponse.Close();
httpWebResponse = client.Request_Post("http://www.qip.ru/reg/register", post_reg);
if (httpWebResponse != null && httpWebResponse.StatusCode == HttpStatusCode.OK)
{
stream = httpWebResponse.GetResponseStream();
using (StreamReader reader = new StreamReader(stream, System.Text.Encoding.UTF8))
{
sHTML = reader.ReadToEnd();
}
}
}
Вообщем то все.
Осталось добавить многопоточность и всем удачи :D
Замечания и предложения приветствуются. :)