协程
# # 协程 # import asyncio # import time # # # 创建一个协程对象 # #定义一个特殊函数,特殊:调用后返回一个协程对象,且函数内部的实现语句不会立即执行 # async def request(url): # print("start",url) # time.sleep(1) # print("end",url) # # # 创建任务对象,对协程对象封装 # a=request('aaa') # # task=asyncio.ensure_future(a) # # # # 创建一个事件循环对象 # loop=asyncio.get_event_loop() # # 将任务对象注册到该对象中,并启动事件循环 # loop.run_until_complete(task) # # 任务对象绑定回调 # import asyncio # import time # # async def request(url): # print("start",url) # time.sleep(1) # print("end",url) # return url # # # 回调函数 # # #定义一个任务对象的回调函数 # #task参数表示的就是该函数被绑定的那个任务对象 # def task_back(task): # print("i am tadk_back") # print(task.result()) # # # 任务对象 # a=request("www.1.com") # task=asyncio.ensure_future(a) # # 回调 # task.add_done_callback(task_back) # # loop=asyncio.get_event_loop() # loop.run_until_complete(task) # # 多任务异步协程 # import asyncio # import time # # start=time.time() # async def request(url): # print("start",url) # # time模块是不支持异步 # # time.sleep(2) # # # 阻塞操作必须使用await关键字进行挂起 # await asyncio.sleep(2) # # # # print("end",url) # return url # # # def task_back(task): # print("i am task_back") # print(task.result()) # # urls=[ # 'www.1.com', # 'www.2.com', # 'www.3.com', # ] # # # #多任务列表:存放多个任务对象 # tasks=[] # for url in urls: # a=request(url) # task=asyncio.ensure_future(a) # # task.add_done_callback(task_back) # # 将多个任务对象装在到一个任务列表中 # tasks.append(task) # # loop=asyncio.get_event_loop() # #多任务注册 # # wait 就是将任务列表中的任务对象挂起 # loop.run_until_complete(asyncio.wait(tasks)) # # print(time.time()-start)
多任务异步爬虫测试
from flask import Flask import time app=Flask(__name__) @app.route("/aaa") def aaa(): time.sleep(2) return "aaa" @app.route("/bbb") def bbb(): time.sleep(2) return "bbb" @app.route("/ccc") def ccc(): time.sleep(2) return "ccc" if __name__ == '__main__': app.run()
#多任务异步爬虫测试 # 测试发现 requests 不支持异步操作 import asyncio import time import requests start=time.time() # 协程对象 async def request(url): page_text=requests.get(url).text return page_text # 回调函数 def task_back(task): print("callback函数") print(task.result()) urls=[ 'http://127.0.0.1:5000/aaa', 'http://127.0.0.1:5000/bbb', 'http://127.0.0.1:5000/ccc', ] tasks=[] for url in urls: c=request(url) task=asyncio.ensure_future(c) task.add_done_callback(task_back) tasks.append(task) loop=asyncio.get_event_loop() loop.run_until_complete(asyncio.wait(tasks)) print(time.time()-start) # 测试失败
aiohttp
# - aiohttp模块:是一个支持异步的网络请求模块 # - pip install aiohttp # 在特殊函数内部不可以出现不支持异步模块相关的代码 # 简单的基本架构: # 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关键字进行手动挂起操作 import aiohttp import time import asyncio headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36' } start = time.time() # 协程对象 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 # 回调函数 def parse(task): print("回调函数测试") print(task.result()) urls = [ 'http://127.0.0.1:5000/aaa', 'http://127.0.0.1:5000/bbb', 'http://127.0.0.1:5000/ccc', ] # 测试最大异步任务量 最大任务量约为500 # urls=[] # for i in range(500): # urls.append('http://127.0.0.1:5000/ccc') 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 import time import requests from lxml import etree headers={ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36' } # 采用requsts 获得数据 # all_titles=[] # url='http://wz.sun0769.com/index.php/question/questionType?type=4&page=%d' # for page in range(2): # page=page*30 # new_url=format(url%page) # # response=requests.get(url=new_url,headers=headers) # page_text=response.text # 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].encode("iso-8859-1").decode("gbk") # all_titles.append(title) # print(all_titles) # 协程对象 # 目前出现问题 'gb2312' codec can't decode byte 0x85 in position 26952: illegal multibyte sequence async def request(url): async with aiohttp.ClientSession() as s: async with await s.get(url=url,headers=headers) as response: page_text = await response.text() return page_text start=time.time() all_titles = [] # 回调函数 def parse(task): page_text=task.result() # page_text=page_text.encode("iso-8859-1").decode("gbk") 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] all_titles.append(title) print(all_titles) # 请求列表 urls=[] url='http://wz.sun0769.com/index.php/question/questionType?type=4&page=%d' for page in range(1): page=page*30 new_url=format(url%page) urls.append(new_url) 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))
selenim
selenium模块的使用
- 概念:就是一个基于浏览器自动化的模块。
- selenium和爬虫之间的关联
- 很便捷的捕获动态加载的数据 - 可见即可得
- 实现模拟登陆
- 使用
- 环境的安装:
- pip install selenium
- 下载一个浏览器的驱动程序
- 谷歌驱动下载:http://chromedriver.storage.googleapis.com/index.html
- 驱动程序和浏览器版本的映射关系:http://blog.csdn.net/huilan_same/article/details/51896672
- 创建某一款一个浏览器对象
- 动作链
- 如果想要触发一系列连续的行为动作
记得放置谷歌驱动
测试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()
使用selenim
from selenium import webdriver from time import sleep # 指定浏览器驱动位置,记得前面加r'','r'是防止字符转义的 bro=webdriver.Chrome(executable_path=r'chromedriver.exe') # 发起请求 bro.get("https://www.jd.com/") #在搜索框中搜索商品 #可以使用find系列的方法进行标签定位 search_input=bro.find_element_by_xpath('//*[@id="key"]') #想搜索框中写入商品名称 search_input.send_keys('iphone') 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)') page_text=bro.page_source with open('./jingdong.html','w',encoding='utf-8') as fp: fp.write(page_text) sleep(1) bro.quit()
动作链
from selenium import webdriver # 动作链 from selenium.webdriver import ActionChains from time import sleep # 指定浏览器驱动位置,记得前面加r'','r'是防止字符转义的 bro=webdriver.Chrome(executable_path=r'chromedriver.exe') # 发起请求 # 选择 测试 https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable bro.get("https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable") # 定位要拖动的标签 #定位的标签是存在于iframe的子页面中,如果直接使用find做定位,是定位不到的 # target_ele=bro.find_element_by_id('draggable') # print(target_ele) # 若要定位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(2) bro.close()
总结
1.什么是代理?代理和爬虫之间的关联是什么? 2.在requests的get和post方法常用的参数有哪些?分别有什么作用?(四个参数) - url headers parmas/data proxies 3.在爬虫中如何处理cookie相关的操作?(两种方式) - 手动 - 自动 4.什么是动态请求参数?通常情况下如何捕获动态请求参数呢? - 每次请求都会发生变化的请求参数 - 通常情况下会被隐藏在前台页面 5.代理中的匿名度都有哪些?分别表示什么意思 6.什么是代理的类型?不同类型代理的区别是什么? - http - https 7.简述线程池中map方法的使用方式和其作用 func_return = map(func,list) 单线程+多任务异步协程 v3.6 - 意义:提升爬取数据的效率 - 实现异步爬虫的方式 - 多线程/多进程(不建议) - 池(适当) - 单线程+多任务异步协程(推荐) - 概念 - 协程:协程对象。可以使用async关键字修饰一个函数的定义(特殊的函数),当该特殊的函数被调用后,就可以返回一个协程对象。 当函数调用后,函数内部的实现语句不会被立即执行。 - 协程 == 特殊函数 - 任务对象: - 本质上就是对协程对象进一步封装。 - 任务对象 == 特殊函数 - 给任务对象绑定一个回调 - add_done_callback(callback) - 事件循环(EventLoop):无限的循环对象 - 我们必须将任务对象注册到事件循环对象中,然后开启事件循环对象。 - 事件循环对象在执行任务对象的时候是基于异步 - await async - 注意事项: - 保证特殊函数内部不可以出现不支持异步模块对应的代码 - 在特殊函数内部遇到阻塞操作必须使用await关键字对其进行手动挂起 - 如果想要将多个任务对象注册到事件循环中,必须将多个任务对象封装到一个列表中,然后将列表注册(必须使用wait方法将列表中的任务对象进行挂起)到事件循环中 - aiohttp模块:是一个支持异步的网络请求模块 - pip install aiohttp selenium模块的使用 - 概念:就是一个基于浏览器自动化的模块。 - selenium和爬虫之间的关联 - 很便捷的捕获动态加载的数据 - 可见即可得 - 实现模拟登陆 - 使用 - 环境的安装: - pip install selenium - 下载一个浏览器的驱动程序 - 谷歌驱动下载:http://chromedriver.storage.googleapis.com/index.html - 驱动程序和浏览器版本的映射关系:http://blog.csdn.net/huilan_same/article/details/51896672 - 创建某一款一个浏览器对象 - 动作链 - 如果想要触发一系列连续的行为动作