在我们爬取一些网站的时候,某些功能有可能需要登录,如果连续登录几次的话,会出现验证码,来达到分流或者反爬的效果

"上有政策,下有对策",网站使用验证码来阻止我们爬取内容,我们也有应对验证码的方法,这里我们使用的是云打码平台进行验证码的识别和验证

云打码网址 : http://www.yundama.com/about.html

①, 首先我们要注册账号,普通用户和开发者账号都要注册一下,注册完成之后,登录普通用户的账号,发现题分是0,但是我们测试是需要题分的呀!,可以联系客服,问客服能不能送点,一般是可以的,如果不可以的话,可以自己充值一块钱

②, 然后登录开发者账户,开始操作

③, 点击上方我的软件===>右上角添加新软件,添加一个软件,以便后边使用

④, 然后点击右侧的开发者中心,页面有教程,可以先下载例子查看一下

⑤, 我们使用的是python进行开发,所以下载的时候选择pythonHTTP示例下载

下载成功后的文件夹是这样的

⑥, 这里用的是python3,所以打开python3的文件

打开后可以看到里面是一个类,下面有用户名,密码,密钥,文件之类的信息,我们只需要根据注释,修改这些相关信息就可以了,其他的可以不用动,这样就可以进行验证码的识别了

# 用户名(云打码平台)
username    = 'username'

# 密码(云打码平台)
password    = 'password'                            

# 软件ID,开发者分成必要参数。登录开发者后台【我的软件】获得!
appid       = 1                                     

# 软件密钥,开发者分成必要参数。登录开发者后台【我的软件】获得!
appkey      = '22cc5376925e9387a23cf797cb9ba745'    

# 图片文件,从要爬取的页面获得
filename    = 'getimage.jpg'                        

# 验证码类型,# 例:1004表示4位字母数字,不同类型收费不同。请准确填写,否则影响识别率。在此查询所有类型 http://www.yundama.com/price.html
codetype    = 1004

# 超时时间,秒
timeout     = 60                                    

如果在爬取网页过程中使用的话,我们可以把上面的信息封装成一个函数,调用就可以了,不然每次都要写的话,会很麻烦,下面也会有相应的示例的:

  •  人人网模拟登陆

云打码提供的代码(不需要修改):

 1 import http.client, mimetypes, urllib, json, time, requests
 2 
 3 
 4 ######################################################################
 5 
 6 class YDMHttp:
 7     apiurl = 'http://api.yundama.com/api.php'
 8     username = ''
 9     password = ''
10     appid = ''
11     appkey = ''
12 
13     def __init__(self, username, password, appid, appkey):
14         self.username = username
15         self.password = password
16         self.appid = str(appid)
17         self.appkey = appkey
18 
19     def request(self, fields, files=[]):
20         response = self.post_url(self.apiurl, fields, files)
21         response = json.loads(response)
22         return response
23 
24     def balance(self):
25         data = {'method': 'balance', 'username': self.username, 'password': self.password, 'appid': self.appid,
26                 'appkey': self.appkey}
27         response = self.request(data)
28         if (response):
29             if (response['ret'] and response['ret'] < 0):
30                 return response['ret']
31             else:
32                 return response['balance']
33         else:
34             return -9001
35 
36     def login(self):
37         data = {'method': 'login', 'username': self.username, 'password': self.password, 'appid': self.appid,
38                 'appkey': self.appkey}
39         response = self.request(data)
40         if (response):
41             if (response['ret'] and response['ret'] < 0):
42                 return response['ret']
43             else:
44                 return response['uid']
45         else:
46             return -9001
47 
48     def upload(self, filename, codetype, timeout):
49         data = {'method': 'upload', 'username': self.username, 'password': self.password, 'appid': self.appid,
50                 'appkey': self.appkey, 'codetype': str(codetype), 'timeout': str(timeout)}
51         file = {'file': filename}
52         response = self.request(data, file)
53         if (response):
54             if (response['ret'] and response['ret'] < 0):
55                 return response['ret']
56             else:
57                 return response['cid']
58         else:
59             return -9001
60 
61     def result(self, cid):
62         data = {'method': 'result', 'username': self.username, 'password': self.password, 'appid': self.appid,
63                 'appkey': self.appkey, 'cid': str(cid)}
64         response = self.request(data)
65         return response and response['text'] or ''
66 
67     def decode(self, filename, codetype, timeout):
68         cid = self.upload(filename, codetype, timeout)
69         if (cid > 0):
70             for i in range(0, timeout):
71                 result = self.result(cid)
72                 if (result != ''):
73                     return cid, result
74                 else:
75                     time.sleep(1)
76             return -3003, ''
77         else:
78             return cid, ''
79 
80     def report(self, cid):
81         data = {'method': 'report', 'username': self.username, 'password': self.password, 'appid': self.appid,
82                 'appkey': self.appkey, 'cid': str(cid), 'flag': '0'}
83         response = self.request(data)
84         if (response):
85             return response['ret']
86         else:
87             return -9001
88 
89     def post_url(self, url, fields, files=[]):
90         for key in files:
91             files[key] = open(files[key], 'rb');
92         res = requests.post(url, files=files, data=fields)
93         return res.text
View Code

云打码提供的代码,封装成函数,以便调用:

 1 from 爬虫day03.YDM_YDMHttp import YDMHttp
 2 
 3 
 4 def msg(username,password,img_path,codetype):
 5     # 用户名(云打码平台)
 6     username = username
 7 
 8     # 密码(云打码平台)
 9     password = password
10 
11     # 软件ID,开发者分成必要参数。登录开发者后台【我的软件】获得!
12     appid = 1
13 
14     # 软件密钥,开发者分成必要参数。登录开发者后台【我的软件】获得!
15     appkey = '22cc5376925e9387a23cf797cb9ba745'
16 
17     # 图片文件,从要爬取的页面获得
18     filename = img_path
19 
20     # 验证码类型,# 例:1004表示4位字母数字,不同类型收费不同。请准确填写,否则影响识别率。在此查询所有类型 http://www.yundama.com/price.html
21     codetype = codetype
22 
23     # 超时时间,秒
24     timeout = 10
25 
26     # 检查
27     if (username == 'username'):
28         print('请设置好相关参数再测试')
29     else:
30         # 初始化
31         yundama = YDMHttp(username, password, appid, appkey)
32 
33         # 登陆云打码
34         uid = yundama.login();
35         #print('uid: %s' % uid)
36 
37         # 查询余额
38         balance = yundama.balance();
39         #print('balance: %s' % balance)
40 
41         # 开始识别,图片路径,验证码类型ID,超时时间(秒),识别结果
42         cid, result = yundama.decode(filename, codetype, timeout);
43         print('cid: %s, result: %s' % (cid, result))
View Code

模拟人人网登录,保存登陆后的首页信息代码:

import requests
import urllib
from lxml import etree

#导入之前封装好的函数
from YDM_msg import msg


headers = {
    "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36"
}
url = "http://www.renren.com/SysHome.do"

page_text = requests.get(url=url, headers=headers).text

tree = etree.HTML(page_text)
#这里如果page_text里面对应的img标签里面的src不是完整的url的话,要自己复制图片链接,看看少了什么,自己拼接一下 img_url
= tree.xpath("//*[@id='verifyPic_login']/@src")[0] urllib.request.urlretrieve(url=img_url,filename="code.jpg") #调用函数并传参 code_detail = msg("云打码用户名","云打码密码","./code.jpg",2004) login_url = "http://www.renren.com/ajaxLogin/login?1=1&uniqueTimestamp=2019141546368" #获取session对象,登录成功后cookie会自动保存到session中,所以下面也直接用session发请求 session = requests.Session() #data里面是抓包工具抓到的信息,登录的时候需要携带的参数,
有一部分网站携带的参数是动态的,到页面右击检查,在页面搜索一下key,然后动态获取一下
data = { "email":"用户名", "icode":"", "origURL":"http://www.renren.com/home", "domain":"renren.com", "key_id":"1", "captcha_type":"web_login", "password":"密码密文", "rkey":"rkey", "f":"", } session.post(url=login_url,data=data,headers=headers) index_url = "http://www.renren.com/969892423" index_page_text = session.get(url=index_url,headers=headers).text with open("renren_index.html","w",encoding="utf-8") as f: f.write(index_page_text)

 如果在运行过程中出现ssl的错误,有可能是抓包工具导致的,把抓包工具关掉就可以了,这里使用的抓包工具是fiddler4