爬虫4
不同形式:
get 中 params
post 中 data
await 让出cpu的使用权,让cpu执行下一个协程对象
await 直接跳过(不加),协程自动跳出a.sleep(2)
协程
import asyncio
import time
import requests
start = time.time()
async def request(url):
print('请求前')
response = requests.get(url)
print('请求后')
url = 'http://127.0.0.1:5000/tom'
c = request(url)
print(c) #协程对象 <coroutine object request at 0x0000000003630D00>
task = asyncio.ensure_future(c) # 任务对象和协程对象一样 # 现在还未执行
print(task) # <Task pending coro=<request() running at D: ...
loop = asyncio.get_event_loop()
loop.run_until_complete(task) # 但是这里放c 协程对象会出错 cannot reuse already awaited coroutine
print(task) # <Task finished coro=<request() done, defined at D: ... # 执行完
print(time.time()-start)
多任务回调协程
import asyncio
import time
import requests
start = time.time()
async def request(url):
print('请求前')
response = requests.get(url).text
print('请求后')
return response
def callback(task):
a = task.result()
print(a) # None request.get(url) / .text都是I
print('i am callback')
return a
url = 'http://127.0.0.1:5000/tom'
c = request(url)
print(c) #协程对象 <coroutine object request at 0x0000000003630D00>
task = asyncio.ensure_future(c) # 任务对象和协程对象一样 # 现在还未执行
print(task) # <Task pending coro=<request() running at D: ...
task.add_done_callback(callback) # callback 里没有task参数,前面就是task调用的 # # 报错: asyncio.base_futures.InvalidStateError: Result is not set.
loop = asyncio.get_event_loop()
loop.run_until_complete(task) # 但是这里放c 协程对象会出错 cannot reuse already awaited coroutine
print(task) # <Task finished coro=<request() done, defined at D: ... # 执行完
print(time.time()-start)
多任务异步协程
import asyncio
import time
import requests
start = time.time()
async def request(url):
print('请求前')
response = requests.get(url).text
print('请求后')
return response
def callback(task):
a = task.result()
print(a) # None request.get(url) / .text都是I
print('i am callback')
return a
url = 'http://127.0.0.1:5000/tom'
c = request(url)
print(c) #协程对象 <coroutine object request at 0x0000000003630D00>
task = asyncio.ensure_future(c) # 任务对象和协程对象一样 # 现在还未执行
print(task) # <Task pending coro=<request() running at D: ...
task.add_done_callback(callback) # callback 里没有task参数,前面就是task调用的 # # 报错: asyncio.base_futures.InvalidStateError: Result is not set.
loop = asyncio.get_event_loop()
loop.run_until_complete(task) # 但是这里放c 协程对象会出错 cannot reuse already awaited coroutine
print(task) # <Task finished coro=<request() done, defined at D: ... # 执行完
print(time.time()-start)
多任务异步协程
import asyncio
import time
import requests
import aiohttp
start = time.time()
#
async def request(url):
# print('请求前')
response = requests.get(url).text
print(response)
# print('请求后')
return url
def callback(task):
a = task.result()
print(a) # None request.get(url) / .text都是I 因为我执行函数没有返回 应该是return
return a
urls = [
'http://127.0.0.1:5000/bobo',
'http://127.0.0.1:5000/tom',
'http://127.0.0.1:5000/jay',
]
tasks = []
for url in urls:
c = request(url)
task = asyncio.ensure_future(c)
tasks.append(task)
task.add_done_callback(callback)
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
print(time.time()-start)
aiohttp异步爬虫
import asyncio
import time
import requests
import aiohttp
start = time.time()
# async def request(url):
# # print('请求前')
# response = requests.get(url).text
# print(response)
# # print('请求后')
# return url
async def request(url):
# print('请求前')
async with aiohttp.ClientSession() as s:
async with await s.get(url) as response:
page_text = await response.text()
return page_text
# print('请求后')
# return url
def callback(task):
a = task.result()
print(a) # None request.get(url) / .text都是I 因为我执行函数没有返回 应该是return
return a
urls = [
'http://127.0.0.1:5000/bobo',
'http://127.0.0.1:5000/tom',
'http://127.0.0.1:5000/jay',
]
tasks = []
for url in urls:
c = request(url)
task = asyncio.ensure_future(c)
task.add_done_callback(callback)
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))
seleuim的使用
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()
基本使用
from selenium import webdriver
from time import sleep
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()
动作连
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()
基于selenium爬取药监总局
import os
from selenium import webdriver
from time import sleep
from lxml import etree
bro = webdriver.Chrome(executable_path='chromedriver.exe')
# 发起指定url的请求
bro.get('http://125.35.6.84:81/xk/')
dirName = './yaojian'
if not os.path.exists(dirName):
os.mkdir(dirName)
# 执行js让滚轮向下滑动
for i in range(1, 6):
bro.execute_script('window.scrollTo(0,document.body.scrollHeight)')
page_text = bro.page_source
sleep(2)
print(f'第{i}也')
tree = etree.HTML(page_text)
text = tree.xpath('//*[@id="gzlist"]/li/dl/a/text()')
print(text)
name = dirName + '第{i}页.html'
with open(name, 'w', encoding='utf-8') as fp:
fp.write(page_text)
btn = bro.find_element_by_xpath('//*[@id="pageIto_next"]') # id="pageIto_next"
btn.click()
sleep(2)
bro.quit()
# sleep(4) # //*[@id="pageIto_next"]
# 关闭浏览器
错误:
1 . 第一个动态加载的页面,直接访问的话,肯定访问不出来,需要加载到最后,浪费了1-2个小时. 然后你可以,用滑轮滑到最后,然后就可以了. 都加载出来了.就像州所说的,ajax请求出来了
就是当前页面
2 . 没有sleep,页面没加载出来就跳过了, 时常不对,不是代码错误,哪里有错? 浪费1个半小时,偶然加了个sleep,就可以匹配出来了
btn = bro.find_element_by_xpath('//*[@id="pageIto_next"]') # id="pageIto_next"
都是这个没错的
第1也
['广东凯优立生物科技有限公司', '四川三泰医药科技有限公司', '广州市追梦生物科技有
第2也
['广州美科日用品有限公司', '贵州阿斯科科技开发有限公司', '广西田东增年山茶油有限
第3也
['广州蔻丝恩化妆品科技有限公司', '广州市韩朵化妆品有限公司', '广州市索柔生物科技
第4也
['广州梵花化妆品有限公司', '广州如颜化妆品有限公司', '广州笔匠化妆品有限公司',
第5也
['广西锦生堂生物科技有限公司', '四川隆力奇实业有限公司', '武汉市蓓思美生物科技有
正确结果:不是所有的是第一页, 解析需要时间,sleep两次,滑轮一次,btn一次
day04默写
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
- 创建某一款一个浏览器对象
- 动作链
- 如果想要触发一系列连续的行为动作
- 作业:
- 使用selenium将药监总局的首页的企业名称进行爬取(1-5页)
- http://sc.chinaz.com/tupian/eluosi.html 将站长素材中的高清图片进行爬取