2012-09-22 86 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')