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爬虫模块的使用的更多相关文章

  1. asyncio模块实现单线程-多任务的异步协程

    本篇介绍基于asyncio模块,实现单线程-多任务的异步协程 基本概念 协程函数 协程函数: 定义形式为 async def 的函数; aysnc 在Python3.5+版本新增了aysnc和awai ...

  2. 【Python3爬虫】使用异步协程编写爬虫

    一.基本概念 进程:进程是一个具有独立功能的程序关于某个数据集合的一次运行活动.进程是操作系统动态执行的基本单元. 线程:一个进程中包含若干线程,当然至少有一个线程,线程可以利用进程所拥有的资源.线程 ...

  3. Python用yield form 实现异步协程爬虫

    很古老的用法了,现在大多用的aiohttp库实现,这篇记录仅仅用做个人的协程底层实现的学习. 争取用看得懂的字来描述问题. 1.什么是yield 如果还没有怎么用过的话,直接把yield看做成一种特殊 ...

  4. Python核心框架tornado的异步协程的2种方式

    什么是异步? 含义 :双方不需要共同的时钟,也就是接收方不知道发送方什么时候发送,所以在发送的信息中就要有提示接收方开始接收的信息,如开始位,同时在结束时有停止位 现象:没有共同的时钟,不考虑顺序来了 ...

  5. 小爬爬4.协程基本用法&&多任务异步协程爬虫示例(大数据量)

    1.测试学习 (2)单线程: from time import sleep import time def request(url): print('正在请求:',url) sleep() print ...

  6. 爬虫必知必会(4)_异步协程-selenium_模拟登陆

    一.单线程+多任务异步协程(推荐) 协程:对象.可以把协程当做是一个特殊的函数.如果一个函数的定义被async关键字所修饰.该特殊的函数被调用后函数内部的程序语句不会被立即执行,而是会返回一个协程对象 ...

  7. python爬虫--多任务异步协程, 快点,在快点......

    多任务异步协程asyncio 特殊函数: - 就是async关键字修饰的一个函数的定义 - 特殊之处: - 特殊函数被调用后会返回一个协程对象 - 特殊函数调用后内部的程序语句没有被立即执行 - 协程 ...

  8. Python爬虫进阶 | 异步协程

    一.背景 之前爬虫使用的是requests+多线程/多进程,后来随着前几天的深入了解,才发现,对于爬虫来说,真正的瓶颈并不是CPU的处理速度,而是对于网页抓取时候的往返时间,因为如果采用request ...

  9. Python中异步协程的使用方法介绍

    1. 前言 在执行一些 IO 密集型任务的时候,程序常常会因为等待 IO 而阻塞.比如在网络爬虫中,如果我们使用 requests 库来进行请求的话,如果网站响应速度过慢,程序一直在等待网站响应,最后 ...

随机推荐

  1. ubuntu配置定时任务crontab何保存退出

    crontab -e配置完成后,如何把保存并退出? 1.Ctrl+o 写入 2.出现“FIile name to Write...”,输入Enter 3.Ctrl+x 保存输出 提示“crontab: ...

  2. 架构篇 | 带你轻松玩转 LAMP 网站架构平台(一)

    作者 | JackTian 微信公众号 | 杰哥的IT之旅(ID:Jake_Internet) 转载请联系授权(微信ID:Hc220066)备注:来自博客园 1.什么是 LAMP 架构? LAMP 架 ...

  3. SDN Reading Notes

    网络操作编程语言:Frenetic QoS策略实施框架:PolicyCop    

  4. [NOI2009][codevs1846]KCOJ0191]植物大战僵尸

    题目描述 Description Plants vs. Zombies(PVZ)是最近十分风靡的一款小游戏.Plants(植物)和Zombies(僵尸)是游戏的主角,其中Plants防守,而Zombi ...

  5. ESA2GJK1DH1K基础篇: 硬件使用说明

    开发板板载介绍 一.示意图 1.单片机:STM32C8T6 2.Wi-Fi模块:ESP8266 3.GPRS模块:Air202 4.温湿度传感器:DHT11 5.液晶:OLED(IIC) 6.继电器 ...

  6. helm原理

    Helm: helm就相当于Linux的包管理工具yum,但它管理的程序包是一些打包好的清单文件. 其核心术语: Chart:一个helm程序包,它里面可理解为,包含了一下定义Pod的清单文件,这些清 ...

  7. QAbstractItemModel详细剖析 …&&... QAbstractTableModel

    从函数开始: QModelIndex QAbstractTableModel::sibling(int row, int column,  QModelIndex &idx) const;  ...

  8. Android Studio 之 控件基础知识

    1. TextView 和 EditText 控件常用属性  android:layout_width="match_parent" 宽度与父控件一样宽 android:layou ...

  9. [JS]截取字符,中英文都可以

    //截取字符,中英文都可以,hasDot=true 返回值的最后还可以添加3个点 function subString(str, len, hasDot) { var newLength = 0; v ...

  10. myeclipse导入项目后中文乱码

    window----preference ----general-----workspace-------text file encoding 可以多测试下:gbk,utf-8.....