2012-09-22 80 views
1

我正在嘗試使用python腳本登錄維基百科,但儘管遵循了here的說明,但我無法使其正常工作。使用python登錄網站

import urllib 
import urllib2 
import cookielib 

username = 'myname' 
password = 'mypassword' 

cj = cookielib.CookieJar() 
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj)) 
opener.addheaders = [("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6")] 
login_data = urllib.urlencode({'wpName' : username, 'wpPassword' : password}) 
opener.open('http://en.wikipedia.org/w/index.php?title=Special:UserLogin', login_data) 
resp = opener.open('http://en.wikipedia.org/wiki/Special:Watchlist') 

我得到的只是「你沒有登錄」頁面。我試圖用腳本登錄到另一個站點,結果相同。我懷疑這要麼與cookie有關,要麼我在這裏錯過了一些非常簡單的事情。但我無法找到它。

+2

嘗試使用WireShark或類似的工具來檢查通過網站登錄時,所有的數據包,你應該看到什麼Web應用程序實際發送到服務器。 – LavaScornedOven

+0

您可以使用「live http header firefox」或「chrome developer tools」來查看一旦您點擊登錄按鈕後發送的所有請求。正如我看到你在'login_data'中缺少了一些東西。 – RanRag

+0

嗯,這意味着我需要先獲取令牌並將其與我的用戶名和密碼一起發送? – Conti

回答

1

如果您檢查發送到登錄URL(用工具如Charles Proxy的幫助下)的原始請求,你會看到,它實際上是發送4個參數:wpNamewpPasswordwpLoginAttemptwpLoginToken。前3個是靜態的,你可以隨時填寫,但是第4個需要從登錄頁面的HTML中解析出來。除了其他3之外,您還需要將此解析的值發佈到登錄URL以便能夠登錄。

下面是使用工作代碼RequestsBeautifulSoup

import requests 
from bs4 import BeautifulSoup as bs 


def get_login_token(raw_resp): 
    soup = bs(raw_resp.text, 'lxml') 
    token = [n.get('value', '') for n in soup.find_all('input') 
      if n.get('name', '') == 'wpLoginToken'] 
    return token[0] 

payload = { 
    'wpName': 'my_username', 
    'wpPassword': 'my_password', 
    'wpLoginAttempt': 'Log in', 
    #'wpLoginToken': '', 
    } 

with requests.session() as s: 
    resp = s.get('http://en.wikipedia.org/w/index.php?title=Special:UserLogin') 
    payload['wpLoginToken'] = get_login_token(resp) 

    response_post = s.post('http://en.wikipedia.org/w/index.php?title=Special:UserLogin&action=submitlogin&type=login', 
          data=payload) 
    response = s.get('http://en.wikipedia.org/wiki/Special:Watchlist') 
+0

太棒了,那就是訣竅!非常感謝你。 :) 我已經在使用BeautifulSoup進行解析,但我不知道請求。它看起來比urllib平滑得多。從現在開始使用它。 – Conti

+0

@Conti很高興提供幫助,YES'Requests'真棒:) –

+0

@KayZhu - 將[]訪問方法切換爲.get()以允許不存在的屬性;特別是某些表單不會爲所有輸入元素分配「名稱」屬性 - 因此'n.get('name','')'處理這些屬性而不會拋出KeyMissing異常 – jmetz

0

您需要將標題Content-Type: application/x-www-form-urlencoded添加到您的POST請求中。

1

添加上述兩行

r = bs(response.content) 
print r.get_text() 

我應該能夠明白,如果我登錄或沒有,對不對?我一直在看「請登錄查看或編輯您的監視列表上的項目。」但我使用上面給出的乾淨的代碼,以及我的登錄名和密碼。

錯誤在哪裏? 。

0

我還添加了以下幾行,看看自己在不登錄

page = response.text.encode('utf8') 

if page.find('Not logged in'): 
    print 'You are not logged in. :(' 
else: 
    print 'YOU ARE LOGGED IN! :)' 
1

維基百科現在強制HTTPS和要求等參數,並wpLoginAttempt成爲wploginattempt,這裏是KZ初步回答的更新版本:

import requests 
from bs4 import BeautifulSoup as bs 


def get_login_token(raw_resp): 
    soup = bs(raw_resp.text, 'lxml') 
    token = [n.get('value', '') for n in soup.find_all('input') 
      if n.get('name', '') == 'wpLoginToken'] 
    return token[0] 

payload = { 
    'wpName': 'my_username', 
    'wpPassword': 'my_password', 
    'wploginattempt': 'Log in', 
    'wpEditToken': "+\\", 
    'title': "Special:UserLogin", 
    'authAction': "login", 
    'force': "", 
    'wpForceHttps': "1", 
    'wpFromhttp': "1", 
    #'wpLoginToken': '', 
    } 

with requests.session() as s: 
    resp = s.get('https://en.wikipedia.org/w/index.php?title=Special:UserLogin') 
    payload['wpLoginToken'] = get_login_token(resp) 

    response_post = s.post('https://en.wikipedia.org/w/index.php?title=Special:UserLogin&action=submitlogin&type=login', 
          data=payload) 
    response = s.get('https://en.wikipedia.org/wiki/Special:Watchlist')