python爬虫---单线程+多任务的异步协程,selenium爬虫模块的使用
一丶单线程+多任务的异步协程
特殊函数
async def get_request(url):
print('正在请求~~', url)
await asyncio.sleep(2)
print('请求结束!!', url)
协程对象
c = get_request(url)
任务对象
- 1.起始就是对协程对象的进一步封装。
- 2.结论:任务对象==高级的协程对象==特殊的函数调用
- 3.绑定回调:
- 回调函数什么时候被执行?
- 任务对象执行结束后执行回调函数
- task.add_done_callback(func)
- func必须要有一个参数,该参数表示的是该回调函数对应的任务对象
- 回调函数的参数.result():任务对象对应特殊函数内部的返回值
task = asyncio.ensure_future(c)
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
- 请求
- 获取响应数据
'''
多任务的异步爬虫
'''
import asyncio
import time
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:
page_text =await response.text()
return page_text
def parase(task):
'''
# 解析page_text
:param task:
:return:
'''
page_text=task.result()
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 = get_request(url)
task = asyncio.ensure_future(c)
task.add_done_callback(parase)
tasks_list.append(task)
coroutine_list.append(c)
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
捕获动态数据
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_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()的操作才可。
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)
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):
action.move_by_offset(5,0).perform()
time.sleep(0.1)
browser.quit()
无头浏览器
- 无头浏览器
- phantomjs
- 谷歌无头浏览器(推荐)
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
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"
chrome_options.add_experimental_option('excludeSwitches', ['enable-automation'])
browser=webdriver.Chrome('chromedriver.exe',chrome_options=chrome_options)
browser.get('https://www.taobao.com')
三丶12306的模拟登录
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')
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)
browser.save_screenshot('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
size=img_tag.size
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)
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()
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?