协程:协程对象。可以使用async关键字修饰一个函数的定义(特殊的函数),当该特殊的函数被调用后,就可以返回一个协程对象。当函数调用后,函数内部的实现语句不会被立即执行
协程 == 特殊函数
本质上就是对协程对象的进一步封装
任务对象 == 特殊函数
给任务对象绑定一个回调
add_done_callback(callback)
保证特殊函数内部不可以出现不支持异步模块对应的代码
在特殊函数内部遇到阻塞操作必须使用await关键字对其进行手动挂起
如果想要将多个任务对象注册到事件循环中,必须将多个任务对象封装到一个列表中,然后将列表注册(必须使用wait方法将列表中的任务对象进行挂起)到事件循环中
aiohttp模块
是一个支持异步的网络请求模块
pip install aiohttp
selenium模块的使用
概念:就是一个基于浏览器自动化的模块
elenium和爬虫之间的关联
很便捷的捕获动态加载的数据 - 可见即可得
实现模拟登陆
环境的安装:
pip install selenium
下载一个浏览器的驱动程序
谷歌驱动下载:http://chromedriver.storage.googleapis.com/index.html
驱动程序和浏览器版本的映射关系:http://blog.csdn.net/huilan_same/article/details/51896672
#
#根据协程对象封装了一个任务对象
task =
asyncio.ensure_future(c)
print
(task)
#<Task pending coro=<test() running at H:/autoclient/test/test.py:6>>
创建事件并执行
#事件循环对象
async def request(url):
print('正在请求:',url)
time.sleep(2)
print('请求完毕!',url)
c1 = request('www.1.com')
task_A = asyncio.ensure_future(c1)
#创建一个事件循环对象
loop = asyncio.get_event_loop()
#将任务对象注册到该对象中并且启动事件循环
loop.run_until_complete(task_A)
任务对象的绑定回调
import asyncio
import time
async def request(url):
print('正在请求:',url)
time.sleep(2)
print('请求完毕!',url)
return url
#定义一个任务对象的回调函数
#task参数表示的就是该函数被绑定的那个任务对象
def task_callback(task):
print('i am task_callback()')
print(task.result())
#task.result()返回的就是任务对象对应的特殊函数内部的返回值
c = request('www.xxx.com')
task = asyncio.ensure_future(c)
task.add_done_callback(task_callback)
loop = asyncio.get_event_loop()
loop.run_until_complete(task)
多任务异步协程:
import asyncio
import time
start = time.time()
#在特殊函数内部不可以出现不支持异步模块相关的代码
async def request(url):
print('正在请求:',url)
# time.sleep(2)#time模块是不支持异步
await asyncio.sleep(2) #阻塞操作必须使用await关键字进行挂起
print('请求完毕!',url)
return url
urls = [
'www.1.com',
'www.2.com',
'www.3.com'
def task_callback(task):
print(task.result())
tasks = [] #多任务列表:存放多个任务对象
for url in urls:
c = request(url)
task = asyncio.ensure_future(c)
task.add_done_callback(task_callback)
tasks.append(task) #将多个任务对象装在到一个任务列表中
loop = asyncio.get_event_loop()
#多任务注册
#wait就是将任务列表中的任务对象进行挂起
loop.run_until_complete(asyncio.wait(tasks))
print(time.time()-start)
多任务异步爬虫测试:一般开500个协程
flask代码:
from flask import Flask
import time
app = Flask(__name__)
@app.route('/bobo')
def index_bobo():
time.sleep(2)
return 'Hello bobo'
@app.route('/jay')
def index_jay():
time.sleep(2)
return 'Hello jay'
@app.route('/tom')
def index_tom():
time.sleep(2)
return 'Hello tom'
if __name__ == '__main__':
app.run(threaded=True)
爬虫测试代码:
import asyncio
import time
import requests
start = time.time()
#在特殊函数内部不可以出现不支持异步模块相关的代码
async def request(url):
print('正在请求:',url)
response = requests.get(url)
return response.text
urls = [
'http://127.0.0.1:5000/bobo',
'http://127.0.0.1:5000/tom',
'http://127.0.0.1:5000/jay'
def parse(task):
page_text = task.result()
print(page_text+',请求到的数据!!!')
tasks = []
for url in urls:
c = request(url)
task = asyncio.ensure_future(c)
task.add_done_callback(parse)
tasks.append(task)
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
print(time.time()-start)
aiohttp的使用:
mport asyncio
import time
import aiohttp
start = time.time()
#在特殊函数内部不可以出现不支持异步模块相关的代码
#简单的基本架构:
# async def request(url):
# with aiohttp.ClientSession() as s:
# #s.get/post和requests中的get/post用法几乎一样:url,headers,data/prames
# #在s.get中如果使用代理操作:proxy="http://ip:port"
# with s.get(url) as response:
# #获取字符串形式的响应数据:response.text()
# #获取byte类型的:response.read()
# page_text = response.text()
# return page_text
#在当前架构的基础上补充细节即可
#细节1:在每一个with前加上async关键字
#细节2:在get方法前和response.text()前加上await关键字进行手动挂起操作
async def request(url):
async with aiohttp.ClientSession() as s:
#s.get/post和requests中的get/post用法几乎一样:url,headers,data/prames
#在s.get中如果使用代理操作:proxy="http://ip:port"
async with await s.get(url) as response:
#获取字符串形式的响应数据:response.text()
#获取byte类型的:response.read()
page_text = await response.text()
return page_text
# urls = [
# 'http://127.0.0.1:5000/bobo',
# 'http://127.0.0.1:5000/tom',
# 'http://127.0.0.1:5000/jay',
# 'http://127.0.0.1:5000/bobo',
# 'http://127.0.0.1:5000/tom',
# 'http://127.0.0.1:5000/jay',
# 'http://127.0.0.1:5000/bobo',
# 'http://127.0.0.1:5000/tom',
# 'http://127.0.0.1:5000/jay',
urls = []
for i in range(500):
urls.append('http://127.0.0.1:5000/bobo')
def parse(task):
page_text = task.result()
print(page_text+',请求到的数据!!!')
tasks = []
for url in urls:
c = request(url)
task = asyncio.ensure_future(c)
task.add_done_callback(parse)
tasks.append(task)
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
print(time.time()-start)
import aiohttp
import asyncio
from lxml import etree
all_titles = []
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36'
async def request(url):
async with aiohttp.ClientSession() as s:
async with await s.get(url,headers=headers) as response:
page_text = await response.text()
return page_text
urls = []
url = 'http://wz.sun0769.com/index.php/question/questionType?type=4&page=%d'
for page in range(100):
u_page = page * 30
new_url = format(url%u_page)
urls.append(new_url)
tasks = []
def parse(task):
page_text = task.result()
page_text = page_text.encode('gb2312').decode('gbk')
tree = etree.HTML(page_text)
tr_list = tree.xpath('//*[@id="morelist"]/div/table[2]//tr/td/table//tr')
for tr in tr_list:
title = tr.xpath('./td[2]/a[2]/text()')[0]
print(title)
all_titles.append(title)
for url in urls:
c = request(url)
task = asyncio.ensure_future(c)
task.add_done_callback(parse)
tasks.append(task)
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
selenim演示:
from selenium import webdriver
from time import sleep
# 后面是你的浏览器驱动位置,记得前面加r'','r'是防止字符转义的
driver = webdriver.Chrome(r'chromedriver.exe')
# 用get打开百度页面
driver.get("http://www.baidu.com")
# 查找页面的“设置”选项,并进行点击
driver.find_elements_by_link_text('设置')[0].click()
sleep(2)
# # 打开设置后找到“搜索设置”选项,设置为每页显示50条
driver.find_elements_by_link_text('搜索设置')[0].click()
sleep(2)
# 选中每页显示50条
m = driver.find_element_by_id('nr')
sleep(2)
m.find_element_by_xpath('//*[@id="nr"]/option[3]').click()
m.find_element_by_xpath('.//option[3]').click()
sleep(2)
# 点击保存设置
driver.find_elements_by_class_name("prefpanelgo")[0].click()
sleep(2)
# 处理弹出的警告页面 确定accept() 和 取消dismiss()
driver.switch_to_alert().accept()
sleep(2)
# 找到百度的输入框,并输入 美女
driver.find_element_by_id('kw').send_keys('美女')
sleep(2)
# 点击搜索按钮
driver.find_element_by_id('su').click()
sleep(2)
# 在打开的页面中找到“Selenium - 开源中国社区”,并打开这个页面
driver.find_elements_by_link_text('美女_百度图片')[0].click()
sleep(3)
# 关闭浏览器
driver.quit()
selenium的基本使用:
from selenium import webdriver
from time import sleep
//chromedriver.exe 浏览器的驱动文件
bro = webdriver.Chrome(executable_path='chromedriver.exe')
#发起指定url的请求
bro.get('https://www.jd.com/')
#在搜索框中搜索商品
#可以使用find系列的方法进行标签定位
search_input = bro.find_element_by_xpath('//*[@id="key"]')
#想搜索框中写入商品名称
search_input.send_keys('iphonex')
sleep(2)
btn = bro.find_element_by_xpath('//*[@id="search"]/div/div[2]/button')
btn.click()
sleep(2)
#执行js让滚轮向下滑动,滑动一屏
bro.execute_script('window.scrollTo(0,document.body.scrollHeight)')
sleep(2)
# bro.execute_script('window.scrollTo(0,-document.body.scrollHeight)')
page_text = bro.page_source
with open('./jingdong.html','w',encoding='utf-8') as fp:
fp.write(page_text)
print(page_text)
sleep(4)
#关闭浏览器
bro.quit()
selenium的动作链
from selenium import webdriver
from selenium.webdriver import ActionChains #动作连
from time import sleep
bro = webdriver.Chrome(executable_path='chromedriver.exe')
bro.get('https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
#定位要拖动的标签
#定位的标签是存在于iframe的子页面中,如果直接使用find做定位,是定位不到的
# target_ele = bro.find_element_by_id('draggable')
#像定位iframe中子页面中的标签必须进行如下操作
bro.switch_to.frame('iframeResult')
target_ele = bro.find_element_by_id('draggable')
#基于动作连实现滑动操作
action = ActionChains(bro)
#点击且长按
action.click_and_hold(target_ele)
for i in range(5):
#perform()表示立即执行动作连指定好的动作
action.move_by_offset(17,0).perform()
sleep(0.5)
action.release()
sleep(4)
bro.quit()