虽然我在这方面并不是特别先进,但我过去在使用 urrlib2、requests 和 scrapy 方面取得了一些成功,但这让我很难过。因此,经过大量搜索并将我的头撞在键盘上之后,我会继续询问。
我想获取网站的 html 源代码,但是在使用我的用户名和密码后,我不断收到一个页面,上面说我的用户名和密码错误。它们在浏览器中运行良好,并且一旦登录,源代码就很容易获得(通过浏览器)。但我似乎无法通过 python/终端获得相同的结果。我将在下面包括我的一些尝试(从这些有用的页面中获得):
使用 urllib2:
req = Request(website, headers={ 'User-Agent': 'Mozilla/5.0' })
base64string = base64.encodestring('%s:%s' % (username, password)).replace('\n', '')
req.add_header("Authorization", "Basic %s" % base64string)
readweb = urlopen(req).read()
另一个版本:
passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
passman.add_password(None, theurl, username, password)
authhandler = urllib2.HTTPBasicAuthHandler(passman)
opener = urllib2.build_opener(authhandler)
pagehandle = opener.open(theurl)
return pagehandle.read()
并尝试使用请求:
r = requests.session()
try:
r.post(theurl, data={'username' : 'username', 'password' : 'password', 'remember':'1'})
except:
print('Sorry, Unable to...')
result = r.get(theurl)
return result.text
我也尝试过使用scrapy,但无论我使用哪个库,它都会返回一个页面的html,显示我的密码/详细信息错误。我猜这与我发送的标题/授权(?)有关,但我不太确定。非常感谢任何帮助,请让我知道我可以更新哪些其他细节(我已经为此熬了半夜,所以如果这篇文章没有意义,请原谅我!)
编辑:
以下是对 Prashant 回答的回溯响应(减去密码等):
Traceback (most recent call last):
文件“/Users/Hatsaw/newpy/pras.py”,第 3 行,在 r = requests.get(URL, auth=('username','password')) 文件“/Library/Frameworks/Python.framework/Versions /2.7/lib/python2.7/site-packages/requests-2.9.0-py2.7.egg/requests/api.py”,第 67 行,在获取返回请求('get',url,params=params, **kwargs)文件“/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/requests-2.9.0-py2.7.egg/requests/api.py”,第53行, 在请求返回 session.request(method=method, url=url, **kwargs) 文件”/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/requests-2.9.0 -py2.7.egg/requests/sessions.py”,第 468 行,在请求 resp = self.send(prep, **send_kwargs) 文件“/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/requests-2.9.0-py2.7.egg/requests/sessions.py",第 576 行,在发送 r = adapter.send(request, **kwargs) 文件中" /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/requests-2.9.0-py2.7.egg/requests/adapters.py”,第 437 行,在发送中引发 ConnectionError( e, request=request) requests.exceptions.ConnectionError: HTTPConnectionPool(host='website', port=80): Max retries exceeded with url: /dashboard/ (Caused by NewConnectionError(': 无法建立新连接: [Errno 8] nodename 或 servname 提供,或未知',))7/site-packages/requests-2.9.0-py2.7.egg/requests/adapters.py",第 437 行,在发送中引发 ConnectionError(e, request=request) requests.exceptions.ConnectionError: HTTPConnectionPool(host='网站',端口 = 80):最大重试次数超过了 url:/dashboard/(由 NewConnectionError 引起(':无法建立新连接:[Errno 8] 提供节点名或服务名,或未知'))7/site-packages/requests-2.9.0-py2.7.egg/requests/adapters.py",第 437 行,在发送中引发 ConnectionError(e, request=request) requests.exceptions.ConnectionError: HTTPConnectionPool(host='网站',端口 = 80):最大重试次数超过了 url:/dashboard/(由 NewConnectionError 引起(':无法建立新连接:[Errno 8] 提供节点名或服务名,或未知'))
编辑:
好的,我现在正在使用 mechanize(推荐如下),这就是我要返回的内容(不确定这是我的根本问题的另一个实例还是我无法使用 mechanize!):
Traceback (most recent call last):
文件“/Users/Hatsaw/newpy/pras2.py”,第 13 行,在 browser.form['email'] = 'email address' 文件“build/bdist.macosx-10.6-intel/egg/mechanize/_form.py ”,第 2780 行,setitem 文件“build/bdist.macosx-10.6-intel/egg/mechanize/_form.py”,第 3101 行,find_control 文件“build/bdist.macosx-10.6-intel/egg/mechanize/_form .py”,第 3185 行,在 _find_control mechanize._form.ControlNotFoundError:没有控件匹配名称“电子邮件”
编辑:
仍在为此苦苦挣扎,所以在这个项目的时间用完之前,这是最后的努力,我必须手动进入并获取所有 html!手指交叉。。
好的,所以根据 barny 的建议,我重新使用请求,并且我正在尝试向帖子提供我从成功的浏览器登录中获得的 cookie 信息。我不确定我这样做是否正确,但我正在使用:
cookies = {'PHPSESSID':'5udcifi6p43ma3h1fnpfqghiu0'}
result = sess.get(the_url, cookies=cookies)
现在,目前,我收到了内部服务器错误响应。经过一番研究,aspnet表单似乎是问题所在:
我只是想先检查一下我没有对请求做错什么,然后也许我会按照 Martijn Pieters 在上面的 SO 链接中的推荐探索 BeautifulSoup/robobrowser。
这是html的表单部分要求的内容:
<form name="aspnetForm" method="post" action="" id="aspnetForm">
<div>
<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
<input type="hidden" name="__LASTFOCUS" id="__LASTFOCUS" value="" />
<input type="hidden" name="__VIEWSTATEFIELDCOUNT" id="__VIEWSTATEFIELDCOUNT" value="2" />
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKLTkwNzg1NTQ3OA9kFgJmD2QWAmYPZBYGAgetc." />
<input type="hidden" name="__VIEWSTATE1" id="__VIEWSTATE1" value="ZyBBIEhvbWUVIE5lZ290aWF0ZSBBZ3JlZW1lbnRzEiBSZetc." />
</div>
<script type="text/javascript">
//<![CDATA[
var theForm = document.forms['aspnetForm'];
if (!theForm) {
theForm = document.aspnetForm;
}
function __doPostBack(eventTarget, eventArgument) {
if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
theForm.submit();
}
}
//]]>
</script>
<script src="/WebResource.axd?d=t2SAOwDGkbrEfkmUaMOR9sPLXqgxfeenNayRja3DNK2R8JEcH-StTTuiaqXpzp--PAISn3vzVbWQ7biREwPkibCmbAE1&t=635586505120000000" type="text/javascript"></script>
<script src="/ScriptResource.axd?d=EL6tXtJfNfGSoQwhYtVnYEqw4oKvuwBBI4etc." type="text/javascript"></script>
<script type="text/javascript">
//<![CDATA[
if (typeof(Sys) === 'undefined') throw new Error('ASP.NET Ajax client-side framework failed to load.');
//]]>
</script>
<script src="/ScriptResource.axd?d=qCmNMcECQa0tfmMcZdwJeeOdcyetc." type="text/javascript"></script>
<div>
<input type="hidden" name="__VIEWSTATEGENERATOR" id="__VIEWSTATEGENERATOR" value="FC5C7135" />
<input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEdABB2xJRvPLCcg6GsBqRFCtw6Xg91QEu10etc." />
</div>
所以。一些小问题。
我的“用户/通行证”术语是否必须与源代码匹配,即用户名 = 用户名或用户?:我现在在 html 中找到了这个,但我找到了 'ctl00$cphMain$tbUsername' 和 'ctl00$cphMain $tbPassword'…</p>
我需要将密码和/或用户名作为 base64.encodestring 发送吗?(我不知道这是否是一个问题,但密码包含字符,如!@$ 等)
我需要添加从浏览器中找到的所有 cookie 字段还是仅添加 PHPSESSID?以下是我在 cookie 中的字段:
ASP.NET_SessionId、CFID、CFTOKEN、__atuvc、__utma、__utmb、__utmc、__utmt、__utmz、BRO_CALLME、BRO_ID、BRO_LOGIN、BRO_MEMBER、BROAUTH、ISFULLMEMBER、phpMBLink、__CT_Data、WRUID
- 有网站 (www.website.com)、登录页面 (www.website.com/login),然后是内容 (www.website.com/content)。我认为我使用(成功登录)登录页面中的 cookie 并将其“发送”到内容页面是否正确?我应该手动执行此操作(从浏览器 cookie 信息中输入字段详细信息)还是在代码中执行此操作(因此,在下面的代码中我将使用:cookies = r_login.cookies)?
最后,这是我当前使用的返回内部服务器错误的代码..:
import requests
the_url = 'the_url'
login = the_url + '/login'
content = the_url + '/content'
username = 'username'
password = 'password'
sess = requests.Session()
sess.auth = ('username', 'password')
sess.get(the_url)
payload = {'ctl00$cphMain$tbUsername': username, 'ctl00$cphMain$tbPassword': password}
r_login = sess.post(login, data=payload)
cookies = {'PHPSESSID':'5udcifi6p43ma3h1fnpfqghiu0', 'ASP.NET_SessionId':'aspnet', 'BRO_LOGIN':'bro_login'}
r_data = s.get(content, cookies=cookies, data=payload)
print r_data.text
抱歉,这已经变得相当长了,如果我需要将它分成几个帖子,请告诉我 - 我一开始以为是一个简单的问题已经变成了别的东西!