您的位置:首页 > 产品设计 > UI/UE

Script with Login & UPC & Requests vs Urllib2

2016-03-17 16:14 633 查看
部分转载自:github 知乎爬虫 ZhihuSpider

6 网络爬虫-验证码登陆

Python入门网络爬虫之精华版

介绍

在访问某些网站时,我们最初只是需要提供用户名密码就可以登陆的,比如说豆瓣网,如果我们要是频繁登陆访问,可能这时网站就会出现一个验证码图片,要求我们输入验证码才能登陆,这样在保证用户方便访问的同时,又防止了机器的恶意频繁访问。对于这种情况,我们可以使用代理服务器访问,只需要换个ip地址再次访问,验证码就不会出现了,当然,当验证码再次出现的时候,我们只能再更换ip地址。

如果对于网站首次登陆就需要提供验证码的情况呢?两种办法,我们可以使用cookie登陆,还有就是可以采用验证码识别手段。使用cookie登陆比较简单,但是有时效性问题。而验证码识别虽然是个很好的思路,但是识别的精度又限制了抓取的效率。

如果采用cookie登陆,可以这样实现:首先需要手动登陆网站一次,获取服务器返回的cookie,这里就带有了用户的登陆信息,当然也可以采用获取的cookie登陆该网站的其他页面,而不用再次登陆。具体代码已经实现,详见ZhihuSpider。我们只需要在配置文件中提供用户名密码,及相应的cookie即可。对于不出现验证码的情况,爬虫会提交用户名密码实现post请求登陆,如果失败,才会使用事先提供的cookie信息。

需要说明的是,判断爬虫登陆与否,我们只需要看一下爬取的信息里面是否带有用户信息即可。在使用cookie登陆的时候,还需要不定期更新cookie,以保证爬取顺利进行。

抓取

这一步,你要明确要得到的内容是是什么?是HTML源码,还是Json格式的字符串等。

抓取大多数情况属于get请求,即直接从对方服务器上获取数据。

首先,Python中自带urllib及urllib2这两个模块,基本上能满足一般的页面抓取。另外,requests也是非常有用的包,与此类似的,还有httplib2等等。

Requests:
import requests
response = requests.get(url)
content = requests.get(url).content
print "response headers:", response.headers
print "content:", content
Urllib2:
import urllib2
response = urllib2.urlopen(url)
content = urllib2.urlopen(url).read()
print "response headers:", response.headers
print "content:", content
Httplib2:
import httplib2
http = httplib2.Http()
response_headers, content = http.request(url, 'GET')
print "response headers:", response_headers
print "content:", content


此外,对于带有查询字段的url,get请求一般会将来请求的数据附在url之后,以?分割url和传输数据,多个参数用&连接。

data = {'data1':'XXXXX', 'data2':'XXXXX'}
Requests:data为dict,json
import requests
response = requests.get(url=url, params=data)
Urllib2:data为string
import urllib, urllib2
data = urllib.urlencode(data)
full_url = url+'?'+data
response = urllib2.urlopen(full_url)


对于登陆情况的处理

使用表单登陆

这种情况属于post请求,即先向服务器发送表单数据,服务器再将返回的cookie存入本地。

data = {'data1':'XXXXX', 'data2':'XXXXX'}
Requests:data为dict,json
import requests
response = requests.post(url=url, data=data)
Urllib2:data为string
import urllib, urllib2
data = urllib.urlencode(data)
req = urllib2.Request(url=url, data=data)
response = urllib2.urlopen(req)


使用cookie登陆

使用cookie登陆,服务器会认为你是一个已登陆的用户,所以就会返回给你一个已登陆的内容。因此,需要验证码的情况可以使用带验证码登陆的cookie解决。

import requests
requests_session = requests.session()
response = requests_session.post(url=url_login, data=data)


若存在验证码,此时采用response = requests_session.post(url=url_login, data=data)是不行的,做法应该如下:

response_captcha = requests_session.get(url=url_login, cookies=cookies)
response1 = requests.get(url_login) # 未登陆
response2 = requests_session.get(url_login) # 已登陆,因为之前拿到了Response Cookie!
response3 = requests_session.get(url_results) # 已登陆,因为之前拿到了Response Cookie!


对于反爬虫机制的处理

使用代理

适用情况:限制IP地址情况,也可解决由于“频繁点击”而需要输入验证码登陆的情况。

这种情况最好的办法就是维护一个代理IP池,网上有很多免费的代理IP,良莠不齐,可以通过筛选找到能用的。对于“频繁点击”的情况,我们还可以通过限制爬虫访问网站的频率来避免被网站禁掉。

proxies = {'http':'http://XX.XX.XX.XX:XXXX'}
Requests:
import requests
response = requests.get(url=url, proxies=proxies)
Urllib2:
import urllib2
proxy_support = urllib2.ProxyHandler(proxies)
opener = urllib2.build_opener(proxy_support, urllib2.HTTPHandler)
urllib2.install_opener(opener) # 安装opener,此后调用urlopen()时都会使用安装过的opener对象
response = urllib2.urlopen(url)


时间设置

适用情况:限制频率情况。

Requests,Urllib2都可以使用time库的sleep()函数:

import time
time.sleep(1)


伪装成浏览器,或者反“反盗链”

有些网站会检查你是不是真的浏览器访问,还是机器自动访问的。这种情况,加上User-Agent,表明你是浏览器访问即可。有时还会检查是否带Referer信息还会检查你的Referer是否合法,一般再加上Referer。

headers = {'User-Agent':'XXXXX'} # 伪装成浏览器访问,适用于拒绝爬虫的网站
headers = {'Referer':'XXXXX'}
headers = {'User-Agent':'XXXXX', 'Referer':'XXXXX'}
Requests:
response = requests.get(url=url, headers=headers)
Urllib2:
import urllib, urllib2
req = urllib2.Request(url=url, headers=headers)
response = urllib2.urlopen(req)


对于断线重连

多进程抓取

对于Ajax请求的处理

自动化测试工具Selenium 模拟鼠标点击

验证码识别

知乎爬虫

config.ini

[info]
email = xxxx@163.com
password = xxxx

[cookies]
q_c1 =
cap_id =
_za =
__utmt =
__utma =
__utmb =
__utmc =
__utmz =
__utmv =
z_c0 =
unlock_ticket =


ZhihuSpider.py

# -*- coding: utf-8 -*-
'''
网络爬虫之用户名密码及验证码登陆:爬取知乎网站
'''
import requests
import ConfigParser
def create_session():
cf = ConfigParser.ConfigParser()
cf.read('config.ini')
cookies = cf.items('cookies')
cookies = dict(cookies)
from pprint import pprint
pprint(cookies)
email = cf.get('info', 'email')
password = cf.get('info', 'password')

session = requests.session()
login_data = {'email': email, 'password': password}
header = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36',
'Host': 'www.zhihu.com',
'Referer': 'http://www.zhihu.com/'
}
r = session.post('http://www.zhihu.com/login/email', data=login_data, headers=header)
if r.json()['r'] == 1:
print 'Login Failed, reason is:',
for m in r.json()['data']:
print r.json()['data'][m]
print 'So we use cookies to login in...'
has_cookies = False
for key in cookies:
if key != '__name__' and cookies[key] != '':
has_cookies = True
break
if has_cookies is False:
raise ValueError('请填写config.ini文件中的cookies项.')
else:
# r = requests.get('http://www.zhihu.com/login/email', cookies=cookies) # 实现验证码登陆
r = session.get('http://www.zhihu.com/login/email', cookies=cookies) # 实现验证码登陆

with open('login.html', 'w') as fp:
fp.write(r.content)

return session, cookies
if __name__ == '__main__':
requests_session, requests_cookies = create_session()

# url = 'http://www.zhihu.com/login/email'
url = 'http://www.zhihu.com/topic/19552832'
# content = requests_session.get(url).content # 未登陆
# content = requests.get(url, cookies=requests_cookies).content # 已登陆
content = requests_session.get(url, cookies=requests_cookies).content # 已登陆
with open('url.html', 'w') as fp:
fp.write(content)


UPC 爬虫

数字石大爬虫 待完善

用session保存lt(token)

密码要用md5加密过的

可以不用headers

# coding:utf-8
import requests
import re
import unicodedata
url = 'http://cas.upc.edu.cn/cas/login'
headers = {
'Host': 'cas.upc.edu.cn',
'Referer': 'http://cas.upc.edu.cn/cas/',
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.97 Safari/537.36'
}
s = requests.Session()
r = s.get(url)
# print r.text
ltt = re.findall('<input type="hidden" name="lt" value="(.*?)">', r.text, re.S)[0]
ltu = re.findall('(.*?)" />', ltt, re.S)[0]
lt = unicodedata.normalize('NFKD', ltu).encode('ascii','ignore')
# print lt
postData = {
'encodedService': 'http%3a%2f%2fi.upc.edu.cn%2fdcp%2findex.jsp',
'service': 'http://i.upc.edu.cn/dcp/index.jsp',
'serviceName': 'null',
'loginErrCnt': '0',
'username': '12016222',
'password': 'defac44447b57f152d14f30cea7a73cb',
'lt': lt
}
# print postData

r = s.post(url, params = postData)
# print r.text
url_jwxt = re.findall('<a href="(.*?)">', r.text, re.S)[0]
url_jwxt = unicodedata.normalize('NFKD', url_jwxt).encode('ascii','ignore')
r = s.get(url_jwxt)
# print type(r)
# print r.text
url_jwxt = 'http://i.upc.edu.cn/dcp/forward.action?path=/portal/portal&p=home'
r = s.get(url_jwxt)
# print type(r)
# print r.text
# 居然重定向了两次才进去
# 上面已经进入了数字石大,下面开始重定向到教务系统,下面网址是通过在浏览器中进入数字石大后,在源代码中找到a href的属性标签得来得

url_jwxt = 'http://i.upc.edu.cn/dcp/forward.action?path=dcp/core/appstore/menu/jsp/redirect&appid=1180&ac=3'
headers = {
'User-Agent': 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)'
} # 一个IE的头,但是和不加差不多,都是无法创建对象
r = s.get(url_jwxt, headers = headers)
# print r.text
url_jwxt = 'http://211.87.177.1/jwxt/framework/new_window.jsp?lianjie=&winid=win2'
r = s.get(url_jwxt)
# print r.text # 得到了一个空的左右边栏,下面是点击成绩查询
# 从这里开始就不行了,下面的仅供参考

url_jwxt = 'http://211.87.177.1/jwxt/dwr/call/plaincall/dwrMonitor.emptyMap.dwr'
postData = {
'callCount': '1page=/jwxt/framework/menuleft.jsp?fater=',
'winid': 'win2httpSessionId=C0E60F1756A05E192572A7098C054573scriptSessionId=3CDADE8B1B8E2B7B1BE590D28D3A8B19767c0-scriptName=dwrMonitorc0-methodName=emptyMapc0-id=0c0-param0=string:query_xscj.jspCED39C310ADD0F8BE043C4E516ACA04EbatchId=0'
}
r = s.post(url_jwxt, params = postData)
# print r.text
# print type(r)
postData = {
'kcmc': '',
'kcxz': '',
'kksj': '2015-2016-1',
'ok': '',
'xsfs': 'qbcj'
}

url_jwxt = 'http://211.87.177.1/jwxt/xszqcjglAction.do?method=queryxscj'
r = s.post(url_jwxt, params = postData)
print r.text
# print r.text
# r = s.get(url_jwxt)
# print r.text


选课系统 成绩查询 cookies 待完善

# coding:utf-8
import requests
url = 'http://jwxt.upc.edu.cn/jwxt/Logon.do?method=logon'
headers = {
'Host': 'jwxt.upc.edu.cn',
'Referer': 'http://jwxt.upc.edu.cn/jwxt/Logon.do?method=logon',
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.97 Safari/537.36'
}
cookies = {
'safedog-flow-item': '79B5F2851DC71BCD93B5C1FA76E219EB',
'ASP': 'NET_SessionId=xxal32esbesb0oi21wby2tbx',
'JSESSIONID': '3F4ACB3CD0595A454BECAB723FF72F89'
}  # 使用时先登陆上去替换这里的cookies
cookies = dict(cookies)
print cookies
s = requests.session()
r = s.get(url = url, cookies = cookies, headers = headers)
r1 = requests.get(url) # 未登陆
r2 = s.get(url) # 已登陆,因为之前拿到了Response Cookie!
print r.text


联网登陆账号

可以先输入一个错误的,分析Network中的数据包得到URL

这是SDN实验室里的环境

import requests
url = 'http://222.195.191.231:801/eportal/?c=ACSetting&a=Login&wlanuserip=null&wlanacip=null&wlanacname=null&port=&iTermType=1&session=null'
headers = {
'Host': '222.195.191.231:801',
'Referer': 'http://222.195.191.231/a70.htm',
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.97 Safari/537.36'
}
postData = {
'DDDDD': '12016222',
'upass': '12345679',
'R1': '0',
'R2': '',
'R6': '0',
'para': '00',
'0MKKey': '123456'
}
s = requests.session()
r = s.get(url, params = postData, headers = headers)
# print r.text


这是宿舍里的环境

import requests
url = 'http://222.195.191.230:801/eportal/?c=ACSetting&a=Login&wlanuserip=null&wlanacip=null&wlanacname=null&port=&iTermType=1&session=null'
postData = {
'DDDDD': '12016222@upc',
'upass': '12345679',
'R1': '0',
'R2': '',
'R6': '0',
'para': '00',
'0MKKey': '123456'
} # 这是宿舍的postData,用户名后面要加@upc,url的ip地址可能不同
s = requests.session()
r = s.post(url, params = postData)
print r.text
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: