m.Facebook 配合 C#






4.60/5 (40投票s)
在不使用 Facebook API 的情况下,从 C# 代码执行您 Facebook 个人资料上的基本功能
已采纳建议。请继续提出您的建议、投票和评论,以改进此内容。
有关抓取步骤的指南,请参阅 此处
引言
Facebook Graph API 和许多其他 Facebook C# SDK 允许用户通过代码执行 Facebook 操作。但所有这些都需要 Facebook 应用的应用程序密钥、OATH 权限以及维护会话令牌的记录。我曾想过借助 HTTP GET 和 POST 来实现一些基本任务,例如登录、搜索、更新状态。为此,我使用了 Facebook 网站的移动版本。通过 `HTTPWebRequest`/`Response` 获取 `Response`,然后使用 Regex 解析 HTML 以获取所需数据。在需要时,`Response` 将通过 HTTP `Post` 方法发送。
背景
在我上一篇文章 《C# 中的多线程网页抓取》 中,我解释了使用 Regex、`WebClient` 以及 `HTTPWebRequest` 和 `Response` 进行网页抓取的技术。基于该文章中解释的技术,我编写了附带的代码。本文旨在解释:
- 如何使用 HTTPWebRequest 和 HTTPWebResponse
- 如何向 Web 服务器 GET 和 POST 数据
- 如何收集 Cookie
- 如何维护会话
类方法
名称 |
描述 |
public static Facebook Login(string username, string password) |
获取 WebBrowser 控件的 Cookie 并将其存储在 Cookie Collection 中以维护会话 成功时返回 Facebook 对象,可以通过该对象调用其他公共方法 失败时,在默认浏览器中显示响应 HTML |
public bool StatusUpdate(string txt) |
更新用户时间线上的文本状态 |
public void UploadPhoto(string filepath, string caption) |
将指定路径的图片上传到当前用户配置文件的移动上传文件夹,并附带指定说明 |
public Dictionary<string, string> SearchGroups(string keyword, int scount) |
根据给定的关键字搜索群组,并从指定搜索结果计数开始返回群组 ID 和名称的字典 |
public Dictionary<string, string> SearchPages(string keyword, int scount) |
根据给定的关键字搜索页面,并从指定搜索结果计数开始返回页面 URL 和名称的字典 |
Using the Code
执行登录
Facebook fb = Facebook.Login("USERNAME", "PASSWORD");
状态
fb.StatusUpdate("Text Status");
上传照片
fb.UploadPhoto(@"C:\Users\..\...\...\IMAGE.jpg", "Its the Caption");
搜索群组
Dictionary<string, string> groups;
int startCount = 1; //First Search Result Starts From 1
do
{
groups = fb.SearchGroups("diet coke", startCount);
//Next Page Results will Start From this Count
startCount += groups.Count;
//Traversing Through the Results
string txt = "";
foreach (string k in groups.Keys)
txt += k + "\t\t" + groups[k] + Environment.NewLine;
MessageBox.Show(txt);
} while (groups.Count > 0);
同样的方式,您也可以搜索页面。
代码如何工作?
-
在 C# 执行登录之前,让我们先在 Mozilla 中执行登录,并使用 LiveHTTPHeaders 分析 HTTP 标头。您可以从 Firefox 网站安装 LiveHTTPHeader 插件。启动 LiveHTTPHeader,浏览到 https://#,输入用户名和密码,然后点击登录按钮。浏览器发送的 HTTP Web 请求将如下所示:
-
第一行是发送用户名和密码的 URL(稍后在示例 3 中,我们将看到如何找到此 URL)。第二行指示使用的 HTTP 方法和版本,分别为 POST 和 1.1。
-
然后,所有字段都与我们之前在示例 1 中看到的普通 HTTP 标头一样。重要内容从 Cookie 标头开始。在示例 1 中,当我们浏览到 https://# 时,没有 Cookie 标头,但我们在响应标头中收到了一些 Cookie。现在,当我们点击登录按钮时,之前收到的 Cookie 集将在此 Cookie 标头中发送。
-
下一个标头显示内容类型。POST 数据主要使用两种内容类型:`application/x-www-form-urlencoded` 和 `multipart/form-data`。您可以在 此处 找到有关这些内容的更多信息。
-
下一个标头显示内容长度,最后一行显示内容。您将在该行中看到您的电子邮件地址和密码。实际上,最后一行显示的是通过 HTTP `Post` 方法发送到服务器的数据。
-
还有几个其他值。稍后在示例中,我们将看到这些值是什么,以及从哪里获取这些值!!!
-
让我们检查上面请求的响应标头。
-
响应标头显示了大量 Cookie。这些是服务器在成功登录后颁发的 Cookie。现在,对于任何后续请求,浏览器将这些 Cookie 发送给服务器,这样就可以维护会话。
-
转到“工具”->“清除最近的历史记录”并删除 Cookie,然后尝试浏览到您的 Facebook 个人资料页面,您会发现您将被重定向到 Facebook 登录页面。
- 现在,让我们创建上面截图中的相同登录请求标头,并测试是否能够成功登录。
string getUrl = "https://#/login.php?login_attempt=1"; string postData = "lsd=AVo_jqIy&email=YourEmailAddress &pass=YourPassword&default_persistent=0& charset_test=%E2%82%AC%2C%C2%B4%2C%E2%82%AC%2C%C2%B4%2C%E6%B0%B4%2C%D0%94%2C%D0%84& timezone=-300&lgnrnd=072342_0iYK&lgnjs=1348842228&locale=en_US"; HttpWebRequest getRequest = (HttpWebRequest)WebRequest.Create(getUrl); getRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.2 (KHTML, like Gecko) Firefox 15.0.0.1"; getRequest.CookieContainer = new CookieContainer(); //Adding Previously Received Cookies getRequest.CookieContainer.Add(cookies); getRequest.Method = WebRequestMethods.Http.Post; getRequest.ProtocolVersion = HttpVersion.Version11; getRequest.AllowAutoRedirect = false; getRequest.ContentType = "application/x-www-form-urlencoded"; getRequest.Referer = "https://#"; getRequest.KeepAlive = true;
-
`getUrl` 被分配给数据将要发布的地址,`postData` 变量是上面 HTTP 请求包中内容的副本。然后,我们创建了一个 `HTTPWebRequest` 对象,并设置了它的 User-Agent 标头。
-
在对 https://# 的请求的响应中收到的 Cookie 被添加到 `HTTPWebRequest` 对象中。如果我们不添加这些 Cookie,那么服务器将不会处理我们的登录请求,而是将我们重定向到登录页面。接下来,我们将 HTTP 方法设置为 Post,版本设置为 1.1(用于 HTTPS)。
-
对于我们尝试登录的请求,将 `AllowAutoRedirect` 属性设置为 `false` 非常重要。如果此属性设置为 `true`,那么 `HTTPWebRequest` 对象将跟随重定向响应。在重定向过程中,您可能会丢失对服务器在登录请求响应中发送的 Cookie 的访问权限。
-
现在,让我们将登录信息发送到服务器。
//Converting postData to Array of Bytes byte[] byteArray = Encoding.ASCII.GetBytes(postData); //Setting Content-Length Header of the Request getRequest.ContentLength = byteArray.Length; //Obtaining the Stream To Write Data Stream newStream = getRequest.GetRequestStream(); //Writing Data To Stream newStream.Write(byteArray, 0, byteArray.Length); newStream.Close();
- 数据已写入流,现在让我们获取响应,看看我们收到了哪些 Cookie。
-
我们成功登录了系统并收到了 9 个 Cookie。上面的截图显示了有关收到 Cookie 的少量信息。您可以通过访问 Cookie 的属性来获取更多信息。将收到的 Cookie 添加到全局定义的 CookieCollection 中,以便在后续请求中使用。**如何检查登录是否成功?**通常,Cookie 的数量是判断登录是否成功的一种简单方法。为了更确定,您可以尝试获取主页的 HTML。如果您没有被重定向到登录页面,则表示您已成功登录。
通过这种方式,您可以检查每个任务的发布数据,并编写 Regex 来查找页面 HTML 中的数据,然后生成后续的发布数据请求。上面的大多数函数都使用了这种机制。
关注点
尽管这些只是非常基本的功能,但通过理解这些功能,您可以增强代码以执行更高级的功能,例如加入群组、点赞页面、从时间线获取动态、向群组和页面发布图片、评论帖子、发送好友请求等。
注意:Facebook 类使用 Mozilla Firefox 的用户代理,您应该将其替换为您用于浏览 Facebook 的浏览器的用户代理。
将代码用于任何垃圾邮件活动可能会导致您的帐户被封禁。