python爬虫---单线程+多任务的异步协程,selenium爬虫模块的使用
python爬虫---单线程+多任务的异步协程,selenium爬虫模块的使用
一丶单线程+多任务的异步协程
特殊函数
# 如果一个函数的定义被async修饰后,则该函数就是一个特殊的函数
async def get_request(url):
print('正在请求~~', url)
await asyncio.sleep(2)
print('请求结束!!', url)
协程对象
# - 对象: 特殊函数被调用后,函数内部的实现语句不会被立即执行,然后该函数调用会返回一个协程对象。
# - 结论: 协程对象==特殊的函数调用
### c 是 协程对象
# 函数调用: 返回的是一个协程对象
c = get_request(url) # <generator object get_request at 0x000001C626DCF048
任务对象
# 任务对象
- 1.起始就是对协程对象的进一步封装。
- 2.结论:任务对象==高级的协程对象==特殊的函数调用
- 3.绑定回调:
- 回调函数什么时候被执行?
- 任务对象执行结束后执行回调函数
- task.add_done_callback(func)
- func必须要有一个参数,该参数表示的是该回调函数对应的任务对象
- 回调函数的参数.result():任务对象对应特殊函数内部的返回值
### 任务对象
task = asyncio.ensure_future(c)
### 绑定回调函数 parase ,传入函数名即可
task.add_done_callback(parase)
事件循环对象
# 事件循环对象
- 作用:将其内部注册的任务对象进行异步执行。
### 创建一个事件循环对象
loop = asyncio.get_event_loop()
# 循环执行 , 将任务对象注册到事件循环对象中并且开启事件循环
loop.run_until_complete(asyncio.wait(tasks_list))
编码流程
# 编码流程
- 定义特殊函数
- 创建协程对象
- 封装任务对象
- 创建事件循环对象
- 将任务对象注册到事件循环中且开启事件循环对象
注意事项***
- 注意:在特殊函数内部的实现语句中不可以出现不支持异步的模块对应的代码,否则
就是终止多任务异步协程的异步效果
- 注意重点:requests模块不支持异步,在多任务的异步协程中不可以使用requests
aiohttp模块的使用
- 概念:支持异步的网络请求模块
- 编码流程:
- 写基本架构:
with aiohttp.ClientSession() as s:
with s.get(url) as response:
page_text = response.text()
return page_text
- 补充细节:
- 添加async关键字
- 每一个with前加上async
- 添加await关键字
- 加载每一步的阻塞操作前加上await
- 请求
- 获取响应数据
# -*-coding:utf-8-*-
# Author:Ds
'''
多任务的异步爬虫
'''
import asyncio
import time
# aiohttp 异步网络请求模块
import aiohttp
from lxml import etree
async def get_request(url):
# 开启一个连接请求
async with aiohttp.ClientSession() as s:
# 发送一个连接请求
async with s.get(url=url) as response:
# await 的使用情况:
# 请求和响应都存在网络传输,
page_text =await response.text()
return page_text
def parase(task):
'''
# 解析page_text
:param task:
:return:
'''
# 获取 执行函数调用的结果
page_text=task.result()
# 实例化etree解析对象
tree=etree.HTML(page_text)
page_data=tree.xpath('//*[@id="page"]/a[1]/span[1]/i/@class')[0]
print(page_data)
urls = [
'http://127.0.0.1:5000/ip01',
'http://127.0.0.1:5000/ip02',
'http://127.0.0.1:5000/ip01',
'http://127.0.0.1:5000/ip02',
'http://127.0.0.1:5000/ip01',
'http://127.0.0.1:5000/ip02',
]
start_time = time.time()
# 列表 协程对象列表
coroutine_list = []
# 列表 任务对象列表
tasks_list = []
for url in urls:
### c 是 协程对象
# 函数调用: 返回的是一个协程对象
c = get_request(url) # <generator object get_request at 0x000001C626DCF048
### 任务对象
task = asyncio.ensure_future(c)
### 绑定回调函数
task.add_done_callback(parase)
tasks_list.append(task)
coroutine_list.append(c)
# print(coroutine_list)
# print(tasks_list)
### 创建一个事件循环对象
loop = asyncio.get_event_loop()
# 循环执行 , 将任务对象注册到事件循环对象中并且开启事件循环
loop.run_until_complete(asyncio.wait(tasks_list))
print('总耗时:', time.time() - start_time)
loop.close()
二丶selenium模块
概述
- 概念:基于浏览器自动化的一个模块。
- Appium是基于手机的自动化的模块。
- selenium和爬虫之间的关联
- 便捷的爬取到动态加载的数据
- 可见即可得
- 便捷的实现模拟登陆
基本使用
- 基本使用:
- 环境安装
- pip install selenium
- 下载浏览器的驱动程序
- http://chromedriver.storage.googleapis.com/index.html
- 浏览器版本和驱动程序的映射关系:
https://blog.csdn.net/huilan_same/article/details/51896672
捕获动态数据
# -*-coding:utf-8-*-
# Author:Ds
from selenium import webdriver
import time
from lxml import etree
options=webdriver.ChromeOptions()
options.binary_location = r"E:\Program Files (x86)\Google\Chrome\Application\chrome.exe"
browser=webdriver.Chrome('chromedriver.exe',options=options)
url='https://www.fjggfw.gov.cn/Website/JYXXNew.aspx'
browser.get(url)
time.sleep(1)
# page_source : 获取页面资源 所有数据
page_text=browser.page_source
# 列表存储页面源码数据
all_page_text=[]
for i in range(3):
next_page_btn=browser.find_element_by_xpath('//*[@id="kkpager"]/div[1]/span[1]/a[7]')
next_page_btn.click()
time.sleep(1)
# 往列表里添加一整页数据
all_page_text.append(browser.page_source)
for page_text in all_page_text:
tree=etree.HTML(page_text)
# 获取页面指定动态数据的第一条数据
title=tree.xpath('//*[@id="list"]/div[1]/div/h4/a/text()')[0]
print(title)
动作链
- 动作链
- 在使用find系列的函数进行标签定位的时候如果出现了NoSuchElementException如何处理?
- 如果定位的标签是存在于iframe标签之下的,则在进行指定标签定位的时候
必须使用switch_to.frame()的操作才可。
# -*-coding:utf-8-*-
# Author:Ds
from selenium import webdriver
import time
from lxml import etree
options=webdriver.ChromeOptions()
options.binary_location = r"E:\Program Files (x86)\Google\Chrome\Application\chrome.exe"
browser=webdriver.Chrome('chromedriver.exe',options=options)
browser.get('https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
time.sleep(1)
# 传入iframe的ID #frame的参数为iframe标签的id属性值
browser.switch_to.frame('iframeResult')
# 找到要执行动作的标签元素
div_tag=browser.find_element_by_id('draggable')
# 实例化一个动作链对象, 传入浏览器对象
action=webdriver.ActionChains(browser)
action.click_and_hold((div_tag))
for i in range(3):
# 执行动作链 , perform() 表示立即执行
action.move_by_offset(5,0).perform()
time.sleep(0.1)
browser.quit()
无头浏览器
- 无头浏览器
- phantomjs
- 谷歌无头浏览器(推荐)
# -*-coding:utf-8-*-
# Author:Ds
from selenium.webdriver.chrome.options import Options
from selenium import webdriver
import time
from lxml import etree
# 设置浏览器无头信息
chrome_options=Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
chrome_options.binary_location=r"E:\Program Files (x86)\Google\Chrome\Application\chrome.exe"
browser=webdriver.Chrome('chromedriver.exe',chrome_options=chrome_options)
browser.get('https://www.taobao.com')
# 截图保存
browser.save_screenshot('./taobao_index.png')
print(browser.page_source)
如何规避selenium被监测到的风险
- 如何规避selenium被监测到的风险
- 网站可以根据:'window.navigator.webdriver' 的返回值鉴定是否使用了selenium
- undefind:正常
- true:selenium
# -*-coding:utf-8-*-
# Author:Ds
from selenium.webdriver.chrome.options import Options
from selenium import webdriver
import time
from lxml import etree
# 设置浏览器无头信息
chrome_options=Options()
chrome_options.binary_location=r"E:\Program Files (x86)\Google\Chrome\Application\chrome.exe"
### 设置 不被监测
# console输入: 'window.navigator.webdriver' 为true则检查出是使用的 selenium .
chrome_options.add_experimental_option('excludeSwitches', ['enable-automation'])
browser=webdriver.Chrome('chromedriver.exe',chrome_options=chrome_options)
browser.get('https://www.taobao.com')
三丶12306的模拟登录
# -*-coding:utf-8-*-
# Author:Ds
# 打码平台
from CJY import Chaojiying_Client
# 自动化工具
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver import ActionChains
import time
headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36',
}
# 处理图片模块
from PIL import Image
# 处理图片验证码
def transform(imgPath,imgType):
chaojiying=Chaojiying_Client('打码平台用户','打码平台密码','901821')
# chaojiying2=Chaojiying_Client('bobo328410948', 'bobo328410948', '899370')
img=open(imgPath,'rb').read()
return chaojiying.PostPic(img,imgType)['pic_str']
# 自动化工具设置
chrome_options=Options()
chrome_options.binary_location=r"E:\Program Files (x86)\Google\Chrome\Application\chrome.exe"
# 生成浏览器对象
browser=webdriver.Chrome('chromedriver.exe',chrome_options=chrome_options)
# 发送请求
browser.get('https://kyfw.12306.cn/otn/login/init')
time.sleep(3)
# 截取 整张12306的页面
browser.save_screenshot('main.png')
# 在main.png 中 截取下载验证码
img_tag=browser.find_element_by_xpath('//*[@id="loginForm"]/div/ul[2]/li[4]/div/div/div[3]/img')
# 获取 验证码图片的位置和大小
location=img_tag.location # 最左下角位置(x,y)
size=img_tag.size # img标签对应的图片大小
print(location,size)
# 裁剪范围
rangle=(int(location['x']),int(location['y']),int(location['x'])+size['width'],int(location['y'])+size['height'])
print(rangle) # 左下坐标 和 右上坐标
# 裁取验证码
i=Image.open('./main.png')
frame=i.crop(rangle)
frame.save('./code.png')
# 解析验证码中的内容 , 获得坐标
result=transform('./code.png',9004)
print(result)
time.sleep(2)
# 260,140|260,139 ==> [[260,140],[260,139]]
# 构建数据 '266,77|263,168|199,147'
# all_list=[[x] for x in result.split('|')]
# print(all_list)
all_list=[]
for el in result.split('|'):
x,y=el.split(',')
all_list.append([int(x),int(y)])
print(all_list)
# 循环 打码平台识别出的图片坐标
for x,y in all_list:
# 执行点击动作链
ActionChains(browser).move_to_element_with_offset(img_tag,x,y).click().perform()
time.sleep(0.5)
# 填写用户名
username=browser.find_element_by_xpath('//*[@id="username"]')
username.send_keys('XXXX')
# 填写用户密码
password=browser.find_element_by_xpath('//*[@id="password"]')
password.send_keys('XXXX')
time.sleep(1)
# 点击登录
login_btn=browser.find_element_by_xpath('//*[@id="loginSub"]')
login_btn.click()
# 获取页面资源,保存到本地
page_text=browser.page_source
with open('./traintest.html','w' ,encoding='utf-8') as f:
f.write(page_text)
time.sleep(8)
# 释放浏览器对象资源
browser.quit()
python爬虫---单线程+多任务的异步协程,selenium爬虫模块的使用的更多相关文章
- asyncio模块实现单线程-多任务的异步协程
本篇介绍基于asyncio模块,实现单线程-多任务的异步协程 基本概念 协程函数 协程函数: 定义形式为 async def 的函数; aysnc 在Python3.5+版本新增了aysnc和awai ...
- 【Python3爬虫】使用异步协程编写爬虫
一.基本概念 进程:进程是一个具有独立功能的程序关于某个数据集合的一次运行活动.进程是操作系统动态执行的基本单元. 线程:一个进程中包含若干线程,当然至少有一个线程,线程可以利用进程所拥有的资源.线程 ...
- Python用yield form 实现异步协程爬虫
很古老的用法了,现在大多用的aiohttp库实现,这篇记录仅仅用做个人的协程底层实现的学习. 争取用看得懂的字来描述问题. 1.什么是yield 如果还没有怎么用过的话,直接把yield看做成一种特殊 ...
- Python核心框架tornado的异步协程的2种方式
什么是异步? 含义 :双方不需要共同的时钟,也就是接收方不知道发送方什么时候发送,所以在发送的信息中就要有提示接收方开始接收的信息,如开始位,同时在结束时有停止位 现象:没有共同的时钟,不考虑顺序来了 ...
- 小爬爬4.协程基本用法&&多任务异步协程爬虫示例(大数据量)
1.测试学习 (2)单线程: from time import sleep import time def request(url): print('正在请求:',url) sleep() print ...
- 爬虫必知必会(4)_异步协程-selenium_模拟登陆
一.单线程+多任务异步协程(推荐) 协程:对象.可以把协程当做是一个特殊的函数.如果一个函数的定义被async关键字所修饰.该特殊的函数被调用后函数内部的程序语句不会被立即执行,而是会返回一个协程对象 ...
- python爬虫--多任务异步协程, 快点,在快点......
多任务异步协程asyncio 特殊函数: - 就是async关键字修饰的一个函数的定义 - 特殊之处: - 特殊函数被调用后会返回一个协程对象 - 特殊函数调用后内部的程序语句没有被立即执行 - 协程 ...
- Python爬虫进阶 | 异步协程
一.背景 之前爬虫使用的是requests+多线程/多进程,后来随着前几天的深入了解,才发现,对于爬虫来说,真正的瓶颈并不是CPU的处理速度,而是对于网页抓取时候的往返时间,因为如果采用request ...
- Python中异步协程的使用方法介绍
1. 前言 在执行一些 IO 密集型任务的时候,程序常常会因为等待 IO 而阻塞.比如在网络爬虫中,如果我们使用 requests 库来进行请求的话,如果网站响应速度过慢,程序一直在等待网站响应,最后 ...
随机推荐
- tf.Variable()、tf.get_variable()和tf.placeholder()
1.tf.Variable() tf.Variable(initializer,name) 功能:tf.Variable()创建变量时,name属性值允许重复,检查到相同名字的变量时,由自动别名机制创 ...
- sublime python 配置内容
{"cmd": ["python", "-u", "$file"],"file_regex": &q ...
- sublime ctrl b突然不能用解决方法
Sublime Text 2 ?ctrl+b 如果出现运行为空白,按ctrl+`来显示错误,如下所示,转载了一篇解决方案 ? 文章参考:http://eric.themoritzfamily.com/ ...
- ESP8266MOD、刷可以使用AT指令的固件、作为客户端向贝壳云端发送固定数据
硬件部分 1. ESP8266MOD 2. Micro USB数据线一根 实物图:(小灯不必) 硬件准备好之后,直接用数据线连接到电脑即可,然后找到所对应的COM口,记下来备用! 为ESP8266刷A ...
- 微信小程序 组件 全局样式
配置如下设置 /** * 组件的一些选项 */ options: { addGlobalClass: true },
- Pandas | 04 Panel 面板
面板(Panel)是3D容器的数据.面板数据一词来源于计量经济学,部分源于名称:Pandas - pan(el)-da(ta)-s. 3轴(axis)这个名称旨在给出描述涉及面板数据的操作的一些语义. ...
- qt中窗体全屏
原文地址:https://www.cnblogs.com/wiessharling/p/3750461.html 近期在学习QT时遇到了很多问题这也是其中一个,个人通过在各种书籍和网络上的查阅找到了一 ...
- ESA2GJK1DH1K升级篇: 远程升级准备工作: 使用TCP客户端连接Web服务器实现http下载数据
一,根目录建一个文件 二,使用浏览器访问 http://47.92.31.46:80/1.txt 或者 http://47.92.31.46/1.txt 三,使用TCP客户端访问文件内容 3 ...
- ping-pong buffer
1 什么是pingpong? pingpong是一种数据缓存的手段,通过pingpong操作可以提高数据传输的效率. 2 什么时候需要pingpong? 在两个模块间交换数据时,上一级处理的结果不能马 ...
- 什么是 ZFS文件系统?ZFS概念及特点简介
什么是 ZFS? ZFS(Zettabyte File System)是由SUN公司的Jeff Bonwick领导设计的一种基于Solaris的文件系统,最初发布于20014年9月14日. SUN被O ...