一 . 模拟登陆案例(识别验证码)

 1 . 打码平台 - 云打码 : www.yundama.com 

  使用步骤 :

    - 注册两个账户,普通用户和开发者用户 :

    - 登陆

      普通用户查看余额

      登陆开发者用户 :

        创建一个软件: 我的软件 -> 创建软件

        下载示例代码: 开发者中心 -> 下载最新云打码DLL -> PythonHTTP示例下载

    - 下载后解压缩,如下 :

                              

import http.client, mimetypes, urllib, json, time, requests

######################################################################

class YDMHttp:

    apiurl = 'http://api.yundama.com/api.php'
username = ''
password = ''
appid = ''
appkey = '' def __init__(self, username, password, appid, appkey):
self.username = username
self.password = password
self.appid = str(appid)
self.appkey = appkey def request(self, fields, files=[]):
response = self.post_url(self.apiurl, fields, files)
response = json.loads(response)
return response def balance(self):
data = {'method': 'balance', 'username': self.username, 'password': self.password, 'appid': self.appid, 'appkey': self.appkey}
response = self.request(data)
if (response):
if (response['ret'] and response['ret'] < 0):
return response['ret']
else:
return response['balance']
else:
return -9001 def login(self):
data = {'method': 'login', 'username': self.username, 'password': self.password, 'appid': self.appid, 'appkey': self.appkey}
response = self.request(data)
if (response):
if (response['ret'] and response['ret'] < 0):
return response['ret']
else:
return response['uid']
else:
return -9001 def upload(self, filename, codetype, timeout):
data = {'method': 'upload', 'username': self.username, 'password': self.password, 'appid': self.appid, 'appkey': self.appkey, 'codetype': str(codetype), 'timeout': str(timeout)}
file = {'file': filename}
response = self.request(data, file)
if (response):
if (response['ret'] and response['ret'] < 0):
return response['ret']
else:
return response['cid']
else:
return -9001 def result(self, cid):
data = {'method': 'result', 'username': self.username, 'password': self.password, 'appid': self.appid, 'appkey': self.appkey, 'cid': str(cid)}
response = self.request(data)
return response and response['text'] or '' def decode(self, filename, codetype, timeout):
cid = self.upload(filename, codetype, timeout)
if (cid > 0):
for i in range(0, timeout):
result = self.result(cid)
if (result != ''):
return cid, result
else:
time.sleep(1)
return -3003, ''
else:
return cid, '' def report(self, cid):
data = {'method': 'report', 'username': self.username, 'password': self.password, 'appid': self.appid, 'appkey': self.appkey, 'cid': str(cid), 'flag': ''}
response = self.request(data)
if (response):
return response['ret']
else:
return -9001 def post_url(self, url, fields, files=[]):
for key in files:
files[key] = open(files[key], 'rb');
res = requests.post(url, files=files, data=fields)
return res.text ###################################################################### # 用户名
username = 'username' # 密码
password = 'password' # 软件ID,开发者分成必要参数。登录开发者后台【我的软件】获得!
appid = 1 # 软件密钥,开发者分成必要参数。登录开发者后台【我的软件】获得!
appkey = '22cc5376925e9387a23cf797cb9ba745' # 图片文件
filename = 'getimage.jpg' # 验证码类型,# 例:1004表示4位字母数字,不同类型收费不同。请准确填写,否则影响识别率。在此查询所有类型 http://www.yundama.com/price.html
codetype = 1004 # 超时时间,秒
timeout = 60 # 检查
if (username == 'username'):
print('请设置好相关参数再测试')
else:
# 初始化
yundama = YDMHttp(username, password, appid, appkey) # 登陆云打码
uid = yundama.login();
print('uid: %s' % uid) # 查询余额
balance = yundama.balance();
print('balance: %s' % balance) # 开始识别,图片路径,验证码类型ID,超时时间(秒),识别结果
cid, result = yundama.decode(filename, codetype, timeout);
print('cid: %s, result: %s' % (cid, result)) #######################################

YDMHTTPDemo3.x.py 内容

 2 . 案例一 : 模拟登陆 人人网,爬取个人中心页面的数据 

# 获取验证码的图片识别

import http.client, mimetypes, urllib, json, time, requests

######################################################################

class YDMHttp:

    apiurl = 'http://api.yundama.com/api.php'
username = ''
password = ''
appid = ''
appkey = '' def __init__(self, username, password, appid, appkey):
self.username = username
self.password = password
self.appid = str(appid)
self.appkey = appkey def request(self, fields, files=[]):
response = self.post_url(self.apiurl, fields, files)
response = json.loads(response)
return response def balance(self):
data = {'method': 'balance', 'username': self.username, 'password': self.password, 'appid': self.appid, 'appkey': self.appkey}
response = self.request(data)
if (response):
if (response['ret'] and response['ret'] < 0):
return response['ret']
else:
return response['balance']
else:
return -9001 def login(self):
data = {'method': 'login', 'username': self.username, 'password': self.password, 'appid': self.appid, 'appkey': self.appkey}
response = self.request(data)
if (response):
if (response['ret'] and response['ret'] < 0):
return response['ret']
else:
return response['uid']
else:
return -9001 def upload(self, filename, codetype, timeout):
data = {'method': 'upload', 'username': self.username, 'password': self.password, 'appid': self.appid, 'appkey': self.appkey, 'codetype': str(codetype), 'timeout': str(timeout)}
file = {'file': filename}
response = self.request(data, file)
if (response):
if (response['ret'] and response['ret'] < 0):
return response['ret']
else:
return response['cid']
else:
return -9001 def result(self, cid):
data = {'method': 'result', 'username': self.username, 'password': self.password, 'appid': self.appid, 'appkey': self.appkey, 'cid': str(cid)}
response = self.request(data)
return response and response['text'] or '' def decode(self, filename, codetype, timeout):
cid = self.upload(filename, codetype, timeout)
if (cid > 0):
for i in range(0, timeout):
result = self.result(cid)
if (result != ''):
return cid, result
else:
time.sleep(1)
return -3003, ''
else:
return cid, '' def report(self, cid):
data = {'method': 'report', 'username': self.username, 'password': self.password, 'appid': self.appid, 'appkey': self.appkey, 'cid': str(cid), 'flag': ''}
response = self.request(data)
if (response):
return response['ret']
else:
return -9001 def post_url(self, url, fields, files=[]):
for key in files:
files[key] = open(files[key], 'rb');
res = requests.post(url, files=files, data=fields)
return res.text
######################################################################
# 用户调用这个函数,这个函数在调用上面的函数,进行图片的识别 def getCodeData(username, pwd, codePath, codeType):
username = username # 用户名(云打码普通用户用户名)
password = pwd # 普通用户对应的密码
appid = 6003 # 软件代码,开发者分成必要参数。登录开发者后台【我的软件】获得!
appkey = '1f4b564483ae5c907a1d34f8e2f2776c' # 通讯密钥,开发者分成必要参数。登录开发者后台【我的软件】获得!
filename = codePath # 识别的图片的路径
codetype = codeType # 识别的类型,在帮助文档可查看对应验证码类型
timeout = 20
if (username == 'username'):
print('请设置好相关参数再测试')
else:
# 初始化
yundama = YDMHttp(username, password, appid, appkey) # 登陆云打码
uid = yundama.login();
# print('uid: %s' % uid) # 查询余额
balance = yundama.balance();
# print('balance: %s' % balance) # 开始识别,图片路径,验证码类型ID,超时时间(秒),识别结果
cid, result = yundama.decode(filename, codetype, timeout);
# print('cid: %s, result: %s' % (cid, result)) return result

getCodeData函数

# 人人网的模拟登陆
import requests
import urllib
from lxml import etree
# 获取session对象
session = requests.Session() # 下载验证码图片
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36'
}
url = 'http://www.renren.com'
page_text = requests.get(url=url, headers=headers).text tree = etree.HTML(page_text)
# 获取验证码的图片地址
code_img_url = tree.xpath('//*[@id="verifyPic_login"]/@src')[0]
# 将验证码的地址url保存到本地,然后调用云打码
urllib.request.urlretrieve(url=code_img_url, filename='code.jpg') # 识别验证码图片中的数据值,2004表示4位纯汉字,其他类型代码参考云打码帮助文档
code_data = getCodeData(云打码用户名', '云打码密码', './code.jpg', 2004)
# print(code_data) # code_data为识别结果
# 模拟浏览器登录 ,登录的url
login_url = 'http://www.renren.com/ajaxLogin/login?1=1&uniqueTimestamp=2019141727367'
data = {
"email":"1547360919@qq.com",
"icode":code_data,
"origURL":"http://www.renren.com/home",
"domain":"renren.com",
"key_id":"",
"captcha_type":"web_login",
"password":"38ce96b6b81595f845e55c1dd4e712ad6f1efe50fe31dbd5bf517b273d7c3b6e",
"rkey":"07a9f1810ecf9b507634a45447a628e7",
"f":""
} # 如果请求成功,产生的cookie会自动保存在session对象中
# 使用session进行post请求发送,防止cookie是动态,cookie保存到session对象中
# 可以进行免密登录,
session.post(url=login_url, data=data, headers=headers)
# 登录人人网的主页
url = 'http://www.renren.com/448850039/profile'
page_text = session.get(url=url, headers=headers).text with open('renren.html', 'w', encoding='utf8') as f:
f.write(page_text)

3 . 案例二 : 模拟登录古诗文网 

# 模拟登陆古诗文网
from lxml import etree
import requests s = requests.Session() headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36'
} login_url = 'https://so.gushiwen.org/user/login.aspx?from=http://so.gushiwen.org/user/collect.aspx'
page_text = requests.get(url=login_url, headers=headers, verify=False).text
# verify=False是解决请求https协议问题,SSL错误 tree = etree.HTML(page_text)
img_code_url = 'https://so.gushiwen.org' + tree.xpath('//*[@id="imgCode"]/@src')[0] # 验证码图片请求也会有session产生,因此不能使用urllib的urlretrieve方法
img_data = s.get(url=img_code_url, headers=headers, verify=False).content
with open('./gs_code_img.jpg','wb') as f:
f.write(img_data) # 识别验证码
code_data = getCodeData('bobo328410948', 'bobo328410948', './gs_code_img.jpg', 1004) relogin_url = 'https://so.gushiwen.org/user/login.aspx?from=http%3a%2f%2fso.gushiwen.org%2fuser%2fcollect.aspx'
# 当有些参数是动态变化的时,我们可以去网页源代码中找找
data = {
"__VIEWSTATE":"u+DzAnizDr8zKG7K/Q/OHyl4Kae1i0R5uxnuMk+EONOCJb5GTyGoJgnx1n/wlOx4XePU+CN5dRcmV/ptirBjyW6SyzcQqdOMuyeIbuFfEWNcUm7K00I9RH7g5gA=",
"__VIEWSTATEGENERATOR":"C93BE1AE",
"from":"http://so.gushiwen.org/user/collect.aspx",
"email":"1547360919@qq.com",
"pwd":"512abc...",
"code":code_data,
"denglu":"登录"
}
page_data = s.post(url=relogin_url, data=data, headers=headers, verify=False).text
with open('./gushici.html', 'w', encoding='utf8') as f:
f.write(page_data)

 4 . 随机获取User-Agent 

# 但是因其服务器不稳定,有时候获取不到,因此我们很少用
from fake_useragent import UserAgent
ua = UserAgent(verify_ssl=False,use_cache_server=False).random
headers = {
'User-Agent':ua
} # fake_useragent的安装方式为 pip install fake-useragent

二 . selenium

   selenium是一个第三方库,对外提供的接口可以操作浏览器,然后让浏览器完成自动化操作。可用于获取动态加载的数据。

 1 . 环境搭建 

  - 安装

    pip install selenium

  - 获取某一款浏览器的驱动程序(我用的是谷歌)

    谷歌浏览器驱动下载地址:http://chromedriver.storage.googleapis.com/index.html

    注意:下载的驱动程序必须和浏览器版本统一,大家可以根据 http://blog.csdn.net/huilan_same/article/details/51896672 中提供的版本映射表进行对应

 2 . 编码流程 

  - 导包 : from selenium import webdriver

  - 实例化一款浏览器对象

  - 自制定自动化操作代码

  注意 : 在导包的时候或许会遇到这样的问题

      

    解决 : 原因是因为 --> 开着fiddler抓包软件了,将其关掉就可以了

 3 . 简单代码示例

from selenium import webdriver
from time import sleep
# 参数地址就是 chromedriver.exe的所在目录(驱动路径)
bro = webdriver.Chrome(executable_path=r'D:\@Lily\myproject\pachong\chromedriver.exe')
bro.get(url='https://www.baidu.com/')
sleep(2) text_input = bro.find_element_by_id('kw') # 获取到输入框
text_input.send_keys('人民币')
sleep(2) search_btn = bro.find_element_by_id('su').click() # 获取到搜索按钮,并点击
sleep(2) # 获取当前的页面源码数据
page_text = bro.page_source
print(page_text) bro.quit() # 关闭浏览器

 4 . 示例 : 获取豆瓣电影更多详情数据 

from selenium import webdriver
from time import sleep url = 'https://movie.douban.com/typerank?type_name=%E5%96%9C%E5%89%A7&type=24&interval_id=100:90&action='
bro = webdriver.Chrome(executable_path=r'D:\@Lily\myproject\pachong\chromedriver.exe') bro.get(url=url)
sleep(2) bro.execute_script('window.scrollTo(0,document.body.scrollHeight)')
# 浏览器向下滚动一屏的距离
sleep(2) bro.execute_script('window.scrollTo(0,document.body.scrollHeight)')
# 浏览器向下滚动一屏的距离
sleep(2) bro.execute_script('window.scrollTo(0,document.body.scrollHeight)')
# 浏览器向下滚动一屏的距离
sleep(2) page_text = bro.page_source
with open('./douban.html','w',encoding='utf8') as f:
f.write(page_text) bro.quit()

 5 . 示例 : 模拟登陆爬取QQ空间示例(嵌套iframe框架)

#qq空间
bro = webdriver.Chrome(executable_path=r'D:\@Lily\myproject\pachong\chromedriver.exe')
url = 'https://qzone.qq.com/'
bro.get(url=url)
sleep(2)
#定位到一个具体的iframe
bro.switch_to.frame('login_frame')
bro.find_element_by_id('switcher_plogin').click()
sleep(2) bro.find_element_by_id('u').send_keys('QQ空间用户名')
bro.find_element_by_id('p').send_keys('QQ空间密码') bro.find_element_by_id('login_button').click() sleep(5) page_text = bro.page_source
with open('qq.html','w',encoding='utf-8') as fp:
fp.write(page_text)
bro.quit()

 6 . PhantomJs(无界面浏览器)

  PhantomJS是一款无界面的浏览器,其自动化操作流程和上述操作谷歌浏览器是一致的。由于是无界面的,为了能够展示自动化操作流程,PhantomJS为用户提供了一个截屏的功能,使用save_screenshot函数实现。

# 以获取豆瓣电影为例,仅仅在实例化浏览器对象时有区别,其他并无区别
from selenium import webdriver
from time import sleep url = 'https://movie.douban.com/typerank?type_name=%E5%96%9C%E5%89%A7&type=24&interval_id=100:90&action='
bro = webdriver.Chrome(executable_path=r'D:\@Lily\myproject\pachong\phantomjs.exe') bro.get(url=url)
sleep(2) bro.execute_script('window.scrollTo(0,document.body.scrollHeight)')
# 浏览器向下滚动一屏的距离 sleep(2) bro.execute_script('window.scrollTo(0,document.body.scrollHeight)')
# 浏览器向下滚动一屏的距离
sleep(2) bro.execute_script('window.scrollTo(0,document.body.scrollHeight)')
# 浏览器向下滚动一屏的距离
sleep(2) page_text = bro.page_source
with open('./douban.html','w',encoding='utf8') as f:
f.write(page_text) bro.quit()

 7 . 谷歌无头浏览器

  由于PhantomJs最近已经停止更新和维护了,所以还是推荐使用谷歌无头浏览器,是一款无界面的谷歌浏览器.

#谷歌无头浏览器
from selenium.webdriver.chrome.options import Options # 创建一个参数对象,用来控制chrome以无界面方式打开
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu') #获取豆瓣电影中更多电影详情数据
url = 'https://movie.douban.com/typerank?type_name=%E6%83%8A%E6%82%9A&type=19&interval_id=100:90&action='
bro = webdriver.Chrome(executable_path=r'D:\@Lily\myproject\pachong\chromedriver.exe',chrome_options=chrome_options)
bro.get(url)
sleep(3)
bro.execute_script('window.scrollTo(0,document.body.scrollHeight)')
sleep(3)
bro.execute_script('window.scrollTo(0,document.body.scrollHeight)')
sleep(3)
bro.execute_script('window.scrollTo(0,document.body.scrollHeight)')
sleep(2)
page_text = bro.page_source with open('./douban.html','w',encoding='utf-8') as fp:
fp.write(page_text)
print(page_text)
sleep(1)
bro.quit()

三 . 线程池

   现在使用的是基于 multiprocessing.dummy线程池

1 . 示例 : 爬取梨视频热门视频

# 爬取梨视频数据
import requests
import re
from lxml import etree
#导入线程池模块
from multiprocessing.dummy import Pool
import random # 实例化一个线程池对象
pool = Pool(5)
url = 'https://www.pearvideo.com/category_1'
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36'
}
# 获取首页页面数据
page_text = requests.get(url=url,headers=headers).text
tree = etree.HTML(page_text)
li_list = tree.xpath('//div[@id="listvideoList"]/ul/li') video_url_list = []
for li in li_list:
detail_url = 'https://www.pearvideo.com/'+li.xpath('./div/a/@href')[0]
detail_page = requests.get(url=detail_url,headers=headers).text
video_url = re.findall('srcUrl="(.*?)",vdoUrl',detail_page,re.S)[0]
video_url_list.append(video_url) video_data_list = pool.map(getVideoData, video_url_list)
pool.map(saveVideo, video_data_list) def getVideoData(url):
return requests.get(url=url,headers=headers).content def saveVideo(data):
fileName = str(random.randint(0,5000))+'.mp4'
with open(fileName,'wb') as fp:
fp.write(data)

四 . 总结

  本篇涉及到的反爬机制

    - 验证码

    - 动态加载

模拟登陆,selenium,线程池的更多相关文章

  1. 爬虫之 cookie , 验证码,模拟登陆,线程

    需求文档的定制 糗事百科的段子内容和作者(xpath的管道符)名称进行爬取,然后存储到mysql中or文本 http://sc.chinaz.com/jianli/free.html爬取简历模板 HT ...

  2. Java并发编程之线程池及示例

    1.Executor 线程池顶级接口.定义方法,void execute(Runnable).方法是用于处理任务的一个服务方法.调用者提供Runnable 接口的实现,线程池通过线程执行这个 Runn ...

  3. Python脚本模拟登陆DVWA

    目录 requests模拟登陆 Selenium自动化测试登陆 环境:python3.7 windows requests模拟登陆 我们登陆DVWA的时候,看似只有一步:访问网站,输入用户名和密码,登 ...

  4. 爬虫 requests模块的其他用法 抽屉网线程池回调爬取+保存实例,gihub登陆实例

    requests模块的其他用法 #通常我们在发送请求时都需要带上请求头,请求头是将自身伪装成浏览器的关键,常见的有用的请求头如下 Host Referer #大型网站通常都会根据该参数判断请求的来源 ...

  5. 使用线程池模拟处理耗时任务,通过websocket提高用户体验

    前言 在文章开始之前,询问一下大家平时工作中后端处理批量任务(耗时任务)的时候,前端是如何告知用户任务的执行情况的? 楼主对这个问题想了下,决定使用websokect将这一过程展现给用户. 于是就有了 ...

  6. 使用ThreadGroup模拟线程池

    参考文章: [1]创建线程池 http://sunnylocus.iteye.com/blog/223327?page=2#comments [2]线程组ThreadGroup  http://hub ...

  7. 自定义ThreadPoolExecutor带Queue缓冲队列的线程池 + JMeter模拟并发下单请求

    .原文:https://blog.csdn.net/u011677147/article/details/80271174 拓展: https://github.com/jwpttcg66/GameT ...

  8. 模拟登陆百度以及Selenium 的基本用法

    模拟登陆百度,需要依赖于selenium 模块,调用浏览器,执行python命令 先来说一下这个selenium模块啦...... 本文参考内容来自 Selenium官网 SeleniumPython ...

  9. Selenium模拟登陆百度贴吧

    Selenium模拟登陆百度贴吧 from selenium import webdriver from time import sleep from selenium.webdriver.commo ...

随机推荐

  1. 【java】Map、Set、List不同数据结构的各种不同循环迭代的效率对比,使用场景

    Map.Set.List不同数据结构的各种不同循环迭代的效率对比,使用场景 引申一个地址:Map迭代的使用keySet和entitySet的效率

  2. Oracle 11gR2 RAC 单网卡 转 双网卡绑定 配置步骤

    之前写过一篇双网卡绑定的文章,如下: Oracle RAC 与 网卡绑定 http://blog.csdn.net/tianlesoftware/article/details/6189639 Ora ...

  3. ylb: 数据库备份(Backup)和还原(Restore)

    ylbtech-SQL Server:SQL Server- 数据库备份(Backup)和还原(Restore) -- ======================================== ...

  4. TensorFlow笔记二:线性回归预测(Linear Regression)

    代码: import tensorflow as tf import numpy as np import xlrd import matplotlib.pyplot as plt DATA_FILE ...

  5. Timus : 1002. Phone Numbers 题解

    把电话号码转换成为词典中能够记忆的的单词的组合,找到最短的组合. 我这道题应用到的知识点: 1 Trie数据结构 2 map的应用 3 动态规划法Word Break的知识 4 递归剪枝法 思路: 1 ...

  6. rsync一些常用的命令

    渗透测试的时候会遇到RSYNC 匿名访问 在对一些大型互联网进行测试的时候经常会遇到rsync. 什么是Rsync Rsync(remote synchronize)是一个远程数据同步工具,可通过LA ...

  7. WPF 基础到企业应用系列5——WPF千年轮回 续前缘

    一.摘要 首先非常高兴这个系列能得到大家的关注和支持,前端时间身体状况不适,所以暂停了更新,对此表示非常抱歉,以后会逐渐加快进度.只是因为这是一个非常长的系列,我也想把它写好,所以以后也会慢慢来,在这 ...

  8. Koa2 + Mongoose + Log4js 持久化日志

    代码地址如下:http://www.demodashi.com/demo/12466.html  之前做的项目是采用 Express 框架进行搭建的,其中的日志管理采用了 winston + Post ...

  9. HDFS源码分析数据块汇报之损坏数据块检测checkReplicaCorrupt()

    无论是第一次,还是之后的每次数据块汇报,名字名字节点都会对汇报上来的数据块进行检测,看看其是否为损坏的数据块.那么,损坏数据块是如何被检测的呢?本文,我们将研究下损坏数据块检测的checkReplic ...

  10. linux下复制文件夹命令

    在源文件的目录下,对其进行cp操作,到后面的目标路径,对其进行文件夹复制 cp -rf /home/wangshiming/Downloads/* /home/wangshiming/tools