Использование BrowserSession и HtmlAgilityPack для входа в Facebook через .NET - PullRequest
13 голосов
/ 13 августа 2010

Я пытаюсь использовать класс BrowserSession Рохита Агарвала вместе с HtmlAgilityPack для входа в систему и последующей навигации по Facebook.

Ранее мне удавалось сделать то же самое, написав свой собственный HttpWebRequest.,Тем не менее, он работает только тогда, когда я вручную извлекаю cookie из своего браузера и вставляю новую строку cookie в запрос каждый раз, когда я делаю новый «сеанс».Теперь я пытаюсь использовать BrowserSession, чтобы получить более умную навигацию.

Вот текущий код:

BrowserSession b = new BrowserSession();

b.Get(@"http://www.facebook.com/login.php");
b.FormElements["email"] = "some@email.com";
b.FormElements["pass"] = "xxxxxxxx";
b.FormElements["lsd"] = "qDhIH";
b.FormElements["trynum"] = "1";
b.FormElements["persistent_inputcheckbox"] = "1";

var response = b.Post(@"https://login.facebook.com/login.php?login_attempt=1");

Выше работает нормально.Проблема возникает, когда я пытаюсь использовать эту BrowserSession снова, чтобы получить другую страницу.Я делаю это таким образом, поскольку BrowserSession сохраняет куки из последнего ответа и вставляет их в следующий запрос, поэтому мне больше не нужно вручную вставлять cookiedata, извлеченные из моего браузера.

Однако, когда я пытаюсьсделать что-то вроде этого:

var profilePage = b.Get(@"https://m.facebook.com/profile.php?id=1111111111");

Документ, который я получаю, пуст.Буду признателен за любую информацию о том, что я делаю неправильно.

Ответы [ 6 ]

12 голосов
/ 04 ноября 2012

Я исправил причину этого, если кому-то все равно.Оказывается, куки были сохранены в CookieContainer объекта REQUEST, а не объекта ответа.Я также добавил возможность загрузки файла (при условии, что файл основан на строках).Код определенно НЕ является поточно-ориентированным, но объект не был поточно-ориентированным для начала:

9 голосов
/ 13 августа 2010

Извините, я мало что знаю о пакете гибкости HTML или о классе BrowserSession, о котором вы упомянули.Но я попробовал тот же сценарий с HtmlUnit , и он работал просто отлично.Я использую оболочку .NET (исходный код которой можно найти здесь и объясняется немного подробнее здесь ), и вот код, который я использовал (некоторые деталиснято для защиты невинных):

var driver = new HtmlUnitDriver(true);
driver.Url = @"http://www.facebook.com/login.php";

var email = driver.FindElement(By.Name("email"));
email.SendKeys("some@email.com");

var pass = driver.FindElement(By.Name("pass"));
pass.SendKeys("xxxxxxxx");

var inputs = driver.FindElements(By.TagName("input"));
var loginButton = (from input in inputs
                   where input.GetAttribute("value").ToLower() == "login"
                   && input.GetAttribute("type").ToLower() == "submit"
                   select input).First();
loginButton.Click();

driver.Url = @"https://m.facebook.com/profile.php?id=1111111111";
Assert.That(driver.Title, Is.StringContaining("Title of page goes here"));

Надеюсь, это поможет.

2 голосов
/ 21 декабря 2013

У меня были похожие симптомы - вход в систему работал, но cookie-файл аутентификации отсутствовал в контейнере cookie, поэтому он не был отправлен при последующих запросах. Я узнал, что это произошло потому, что веб-запрос внутренне обрабатывал заголовок Location:, перенаправляя за кулисы на новую страницу, теряя при этом файлы cookie. Я исправил это, добавив:

    request.AllowAutoRedirect = false; // Location header messing up cookie handling!

... для функции OnPreRequest (). Теперь это выглядит так:

    protected bool OnPreRequest(HttpWebRequest request)
    {
        request.AllowAutoRedirect = false; // Location header messing up cookie handling!

        AddCookiesTo(request);               // Add cookies that were saved from previous requests
        if (_isPost) AddPostDataTo(request); // We only need to add post data on a POST request
        return true;
    }

Я надеюсь, что это может помочь кому-то, кто испытывает ту же проблему.

2 голосов
/ 13 августа 2010

Возможно, вы захотите использовать WatiN (Тестирование веб-приложений в .Net) или Selenium для управления вашим браузером. Это поможет вам убедиться, что вам не нужно возиться с cookie-файлами и выполнять какую-либо специальную работу, чтобы последующие запросы работали, поскольку вы имитируете реального пользователя.

1 голос
/ 02 июля 2012

Сегодня я столкнулся с той же проблемой.Я также работал с классом BrowserSession Рохита Агарвала вместе с HtmlAgilityPack.После целого дня проб и ошибок программирования я выяснил, что проблема вызвана тем, что в последующих запросах не были установлены правильные файлы cookie.Я не могу изменить исходный код BrowserSession для правильной работы, но я добавил следующие функции и немного изменил функцию SameCookieFrom.В конце концов, это хорошо сработало для меня.

Добавлены / изменены следующие функции:

class BrowserSession{
   private bool _isPost;
   private HtmlDocument _htmlDoc;
   public CookieContainer cookiePot;   //<- This is the new CookieContainer

 ...

    public string Get2(string url)
    {
        HtmlWeb web = new HtmlWeb();
        web.UseCookies = true;
        web.PreRequest = new HtmlWeb.PreRequestHandler(OnPreRequest2);
        web.PostResponse = new HtmlWeb.PostResponseHandler(OnAfterResponse2);
        HtmlDocument doc = web.Load(url);
        return doc.DocumentNode.InnerHtml;
    }
    public bool OnPreRequest2(HttpWebRequest request)
    {
        request.CookieContainer = cookiePot;
        return true;
    }
    protected void OnAfterResponse2(HttpWebRequest request, HttpWebResponse response)
    {
        //do nothing
    }
    private void SaveCookiesFrom(HttpWebResponse response)
    {
        if ((response.Cookies.Count > 0))
        {
            if (Cookies == null)
            {
                Cookies = new CookieCollection();
            }    
            Cookies.Add(response.Cookies);
            cookiePot.Add(Cookies);     //-> add the Cookies to the cookiePot
        }
    }

Что он делает: Он в основном сохраняет файлы cookie из первоначального «пост-ответа»и добавляет тот же CookieContainer к запросу, вызванному позже.Я не совсем понимаю, почему он не работал в начальной версии, потому что он как-то делает то же самое в функции AddCookiesTo.(if (Cookies! = null && Cookies.Count> 0) request.CookieContainer.Add (Cookies);) В любом случае, с этими добавленными функциями теперь все должно работать нормально.

Его можно использовать так:

//initial "Login-procedure"
BrowserSession b = new BrowserSession();
b.Get("http://www.blablubb/login.php");
b.FormElements["username"] = "yourusername";
b.FormElements["password"] = "yourpass";
string response = b.Post("http://www.blablubb/login.php");

все последующие вызовы должны использовать:

response = b.Get2("http://www.blablubb/secondpageyouwannabrowseto");
response = b.Get2("http://www.blablubb/thirdpageyouwannabrowseto");
...

Я надеюсь, что это поможет многим людям, сталкивающимся с той же проблемой!

0 голосов
/ 13 августа 2010

Вы проверили их новый API?http://developers.facebook.com/docs/authentication/

Вы можете вызвать простой URL-адрес, чтобы получить токен доступа oauth2.0, и прикрепить его к остальным запросам ...

https://graph.facebook.com/oauth/authorize?
    client_id=...&
    redirect_uri=http://www.example.com/oauth_redirect

Измените redirect_uri на любой URL-адресхотите, и он будет вызван обратно с параметром "access_token".Получите это и делайте любые автоматические вызовы SDK, которые вы хотите.

...