2015-12-13 186 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