2015-12-13 132 views
1

我想使用Python Requests-和BeautifulSoup模块登录到Facebook(就像练习一样),我在查找POST参数发送到服务器时遇到了一些问题。Facebook登录使用Python请求和BeautifulSoup

我做的第一件事是,我确定的POST参数,我需要通过手动发送登录到Facebook在浏览器中: description here

然后我写了一些代码来获取Facebook的头版和提取值从登录表单字段:

import requests 
from bs4 import BeautifulSoup 

r = requests.get('https://www.facebook.com/', headers={'user-agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1'}) 
r.encoding = 'utf-8' 
bs = BeautifulSoup(r.text, 'html.parser') 

login_params = { 
    'email': '[email protected]', 
    'pass': 'mypassword', 
    'default_persistent': bs.select('input[name=default_persistent]')[0].get('value'), 
    #'lgndim': bs.select('input[name=lgndim]')[0].get('value'), #Empty value attribute. 
    #'lgnjs': bs.select('input[name=lgnjs]')[0].get('value'), #This one has value="n" for some reason. 
    'lgnrnd': bs.select('input[name=lgnrnd]')[0].get('value'), 
    'locale': bs.select('input[name=locale]')[0].get('value'), 
    'lsd': bs.select('input[name=lsd]')[0].get('value'), 
    #'qsstamp': bs.select('input[name=qsstamp]')[0].get('value'), #This one isn't found at all. 
    #'timezone': bs.select('#u_0_w')[0].get('value'), #Empty value attribute. 
} 

被注释掉的参数是我遇到的那些参数。我可以检索那些输入元素(除了一个),但问题是它们的值属性是空的或错误的。我们以“lgndim”参数为例。当我在我的剧本与BeautifulSoup选择它,我得到这个:

input autocomplete="off" id="u_0_y" name="lgndim" type="hidden" value="" 

但是,当我写的请求,文成HTML文件喜欢这样的:

with open('hello.htm', 'w', encoding='utf8') as f: 
    f.write(r.text) 

并查看我的浏览器中输入元素它看起来像这样:

input autocomplete="off" name="lgndim" value="eyJ3IjoyNTYwLCJoIjoxNDQwLCJhdyI6MjU2MCwiYWgiOjE0MDAsImMiOjI0fQ==" id="u_0_y" type="hidden" 

有人知道这里有什么问题吗?我完全卡住了,任何帮助将不胜感激。我希望我提供了足够的信息。

+2

Facebook不希望您(和其他人)以自动方式登录其页面。各种各样的技巧来防止这种情况。要访问他们的数据,他们提供了几个API和一个Python库。 –

+0

您是否认为Facebook使这些输入值难以访问这样的脚本?另外,你可以用这些他们害怕的自动化脚本来做什么? –

+0

运动,但我认为是超出了范围。没有基于选项的问题。有关更多信息,请阅读Facebook开发人员文档。 –

回答

3

你不能得到一些hidden输入和它的值,因为在浏览器中,它创建并填充了JavaScript,尽管你可以发现它们的值在页面上反向工程脚本或使用非浏览器JavaScript引擎,如phantomjs。

但登录你并不需要做的是,你只需要提取送达脚本一个cookie - datr_js_datr,并使用正则表达式是可能的:

from bs4 import BeautifulSoup 
import requests 
import re 
def facebook_login(mail, pwd): 
    session = requests.Session() 
    r = session.get('https://www.facebook.com/', allow_redirects=False) 
    soup = BeautifulSoup(r.text) 
    action_url = soup.find('form', id='login_form')['action'] 
    inputs = soup.find('form', id='login_form').findAll('input', {'type': ['hidden', 'submit']}) 
    post_data = {input.get('name'): input.get('value') for input in inputs} 
    post_data['email'] = mail 
    post_data['pass'] = pwd.upper() 
    scripts = soup.findAll('script') 
    scripts_string = '/n/'.join([script.text for script in scripts]) 
    datr_search = re.search('\["_js_datr","([^"]*)"', scripts_string, re.DOTALL) 
    if datr_search: 
     datr = datr_search.group(1) 
     cookies = {'_js_datr' : datr} 
    else: 
     return False 
    return session.post(action_url, data=post_data, cookies=cookies, allow_redirects=False) 

如果你检查这功能输出:

>>> facebook_login('[email protected]', 'greatpancake') 
<Response [302]> 

响应状态302 Found表示您已经登录并重定向。

+0

酷,所以通过发送这个'datr'cookie,我可以绕过填写那些空的POST参数的需要。但是,为什么这个工作,我怎么想出来? –

+0

@Justsomeguy,好吧,由JavaScript提供服务的Cookie是使登录安全更为复杂的常用方式。我发现在使用浏览器中的开发人员工具进行逆向工程登录过程中。您可以查看网络日志,并逐个使用不包含请求参数的'curl'并尝试重现预期结果。 – barjomet