Script with Login & UPC & Requests vs Urllib2
2016-03-17 16:14
633 查看
部分转载自:github 知乎爬虫 ZhihuSpider
6 网络爬虫-验证码登陆
Python入门网络爬虫之精华版
如果对于网站首次登陆就需要提供验证码的情况呢?两种办法,我们可以使用cookie登陆,还有就是可以采用验证码识别手段。使用cookie登陆比较简单,但是有时效性问题。而验证码识别虽然是个很好的思路,但是识别的精度又限制了抓取的效率。
如果采用cookie登陆,可以这样实现:首先需要手动登陆网站一次,获取服务器返回的cookie,这里就带有了用户的登陆信息,当然也可以采用获取的cookie登陆该网站的其他页面,而不用再次登陆。具体代码已经实现,详见ZhihuSpider。我们只需要在配置文件中提供用户名密码,及相应的cookie即可。对于不出现验证码的情况,爬虫会提交用户名密码实现post请求登陆,如果失败,才会使用事先提供的cookie信息。
需要说明的是,判断爬虫登陆与否,我们只需要看一下爬取的信息里面是否带有用户信息即可。在使用cookie登陆的时候,还需要不定期更新cookie,以保证爬取顺利进行。
抓取大多数情况属于get请求,即直接从对方服务器上获取数据。
首先,Python中自带urllib及urllib2这两个模块,基本上能满足一般的页面抓取。另外,requests也是非常有用的包,与此类似的,还有httplib2等等。
此外,对于带有查询字段的url,get请求一般会将来请求的数据附在url之后,以?分割url和传输数据,多个参数用&连接。
若存在验证码,此时采用response = requests_session.post(url=url_login, data=data)是不行的,做法应该如下:
这种情况最好的办法就是维护一个代理IP池,网上有很多免费的代理IP,良莠不齐,可以通过筛选找到能用的。对于“频繁点击”的情况,我们还可以通过限制爬虫访问网站的频率来避免被网站禁掉。
Requests,Urllib2都可以使用time库的sleep()函数:
ZhihuSpider.py
密码要用md5加密过的
可以不用headers
这是SDN实验室里的环境
这是宿舍里的环境
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
相关文章推荐
- iOS7 UI兼容 导航栏按钮边框 UINavigationItem left and right padding
- 82. Remove Duplicates from Sorted List II My Submissions Question
- TableView详细解释
- iOS --UIScrollView的学习(一)
- KVC中setValuesForKeysWithDictionary 崩溃问题
- UITableView刷新某一行或某一部分,并记录做项目时的一小心得
- 为什么子线程不能做ui操作
- ant之build.xml基本属性详解
- POJ2431 运用queueq优先队列
- android之handler messagequene looper threadlocal 之间的详细解读
- uipickerview用法
- @RequestBody, @ResponseBody 注解详解(转)
- AS-->如何更高效的使用 Gradle, 快速build apk
- phpQuery对数据信息的采集进一步学习
- @RequestParam @RequestBody @PathVariable 等参数绑定注解详解
- Android Volley 之自定义Request
- 【笔记】《C#大学教程》- 第12章 GUI(一)
- document.getElementById("XXX").innerHTML与document.getElementById("XXX").value
- FineUI(专业版)v3.0.0 发布,手机、平板和桌面全支持!
- 关于UIButton setImage 不显示 和 setTitle不能和谐相处的问题