selenium


selenium

In [ ]:

#演示代码
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

  • 概念:基于浏览器自动化的模块
    • appnium:基于手机应用的自动化模块
  • 环境的安装:
    • pip install selenium
  • 爬虫之间的关联?
    • 实现模拟登陆
    • 便捷帮我们捕获到动态加载的数据(可见即可得)
  • selenium的基本操作
    • 必须提供对应浏览器的驱动程序
    • 谷歌浏览器驱动程序下载地址:
      • http://chromedriver.storage.googleapis.com/index.html
    • 实例化一个浏览器对象
      • bro = webdriver.Chrome(executable_path='驱动程序的路径')
    • 标签定位:
      • find系列的函数
    • senk_keys():向制定标签中录入数据
    • click()
    • js注入:execute_script('jsCode')
    • page_source:返回当前页面的页面源码数据(包含动态加载数据)
  • 缺点:
    • 数据爬取的效率低下

In [9]:

from selenium import webdriver
from time import sleep
#实例化浏览器对象
bro = webdriver.Chrome(executable_path='./chromedriver.exe')
#制定一些自动化的操作

#发起请求
bro.get('https://www.jd.com/')

#标签定位
search_tag = bro.find_element_by_id('key')
#向文本框中录入数据
search_tag.send_keys('mac pro')
sleep(2)
btn = bro.find_element_by_xpath('//*[@id="search"]/div/div[2]/button')
btn.click()
sleep(2)
#js注入execute_script('jsCode')
bro.execute_script('window.scrollTo(0,document.body.scrollHeight)')
sleep(2)
#page_source:返回当前页面的页面源码数据(包含动态加载数据)
print(bro.page_source)

#关闭浏览器
bro.quit()

. . .

In [10]:

from lxml import etree

In [12]:

#使用selenium捕获药监总局的动态加载数据
bro = webdriver.Chrome(executable_path='./chromedriver.exe')
bro.get('http://125.35.6.84:81/xk/')
sleep(1)
#第一页的页面源码数据
page_text = bro.page_source

all_page_text = [page_text]

for i in range(1,4):
    a_tag = bro.find_element_by_xpath('//*[@id="pageIto_next"]')
    a_tag.click()
    sleep(1)
    page_text = bro.page_source
    all_page_text.append(page_text)
    
for page_text in all_page_text:
    tree = etree.HTML(page_text)
    li_list = tree.xpath('//*[@id="gzlist"]/li')
    for li in li_list:
        name = li.xpath('./dl/@title')[0]
        print(name)
    
bro.quit()
厦门莱恩迪贸易发展有限公司
可美科丝化妆品(马鞍山)有限公司
深圳市妆胜化妆品有限公司
湖南旻一生物科技有限公司
江苏普力菲尔日化有限公司
辽宁丽康日用品有限公司
丹东市黄海化妆品厂
宁夏藻谷生物工程有限公司
广州澳莉蔻化妆品有限公司
深圳市舒丽莎日用制品有限公司
永州市嘉华日化实业有限公司
广东福克药业科技有限公司
广州伊妆化妆品有限公司
佳丽宝(广州)生物科技有限公司
广州美启时化妆品有限公司
广州荥美生物科技有限公司
广州蕴美化妆品有限公司
广州御禧坊化妆品有限公司
广州市佳昊生物科技有限公司
广州赛美化妆品有限公司
广州一一生物技术有限公司
广州市柏菲化妆品有限公司
广东康容实业有限公司
浙江伊瑟奇医药科技有限公司
金华美双生物科技有限公司
金华市蔻丽娅化妆品有公司
义乌市鸿艳化妆品有限公司
广东庆昌生物科技有限公司
佛山力格生物科技有限公司
广东微肽生物科技有限公司
广州市东洋丽生物科技股份有限公司
广州市雪蕾化妆品有限公司
广州希黎莎生物科技有限公司
广州蔓缇化妆品有限公司
广东十长生化妆品制造有限公司
扬州市杰飞澳旅游塑胶日化厂
哈尔滨运美达生物科技有限公司
四川丽妍工坊生物科技有限公司
佛山市喜妆化妆品有限公司
江西沃润生物科技有限公司
赣州澳丽尔化妆品有限公司
义乌嘉颜化妆品有限公司
绍兴市春藤日化用品有限公司
广州市有趣生物医药研究院有限公司
广州中草世家化妆品有限公司
广州市佰嘉莉化妆品有限公司
广州市尚昇生物科技有限公司
广州嘉瀛化妆品有限公司
广州歌兰化妆品有限公司
广州创尔美肤生物科技有限公司
广州市露姿化妆品有限公司
广州柏俐臣化妆品科技有限公司
广州蓝雅日用化工有限公司
广州森麦生物科技有限公司
江苏金泽生物科技有限公司
江苏田桥科技实业有限公司
宁波洁美日化科技有限公司
东阳市蝶安芬科技有限公司
广东微研生物科技有限公司
陕西澳美娅生物科技有限公司

1.线程池的基本使用.

import requests
from bs4 import BeautifulSoup
#线程池的模块
from multiprocessing.dummy import Pool
import time
urls = [
    'http://localhost:5000/bobo',
    'http://localhost:5000/jay',
    'http://localhost:5000/tom'
]

#数据的爬取,返回爬取到的页面源码数据
def get_request(url):
    page_text = requests.get(url=url).text
    return page_text

#数据解析
def parse(page_text):
    soup = BeautifulSoup(page_text,'lxml')
    return soup.select('#feng')[0].string

#同步代码
# if __name__ == '__main__':
#     start = time.time()
#     for url in urls:
#         page_text = get_request(url)
#         text_data = parse(page_text)
#         print(text_data)
#     print('总耗时:',time.time()-start)

#异步代码
if __name__ == '__main__':
    start = time.time()

    pool = Pool(3)#实例化线程池对象
    #参数2这个回调函数需要接受参数1列表中的某一个列表元素,回调函数可以对该列表元素进行
        #指定形式的操作
    page_text_list = pool.map(get_request,urls)
    parse_text_list = pool.map(parse,page_text_list)
    print(parse_text_list)
    print('总耗时:',time.time()-start)

2.基于线程池爬取梨视频.

import requests
from lxml import etree
import re
from multiprocessing.dummy import Pool
import random
headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'
}
video_urls = []
main_url = 'https://www.pearvideo.com/category_3'
main_page_text = requests.get(url=main_url,headers=headers).text
#数据解析:每一个视频详情页的url
tree = etree.HTML(main_page_text)
li_list = tree.xpath('//*[@id="listvideoListUl"]/li')
for li in li_list:
    detail_url = "https://www.pearvideo.com/"+li.xpath('./div/a/@href')[0]
    page_text = requests.get(detail_url,headers=headers).text
    ex = 'srcUrl="(.*?)",vdoUrl='
    video_url = re.findall(ex,page_text,re.S)[0]
    video_urls.append(video_url)
# print(video_urls)

def get_video(url):
    video_data = requests.get(url=url,headers=headers).content
    fileName = str(random.randint(0,1000))+'.mp4'
    with open(fileName,'wb') as fp:
        fp.write(video_data)
    print(fileName,"下载成功!!!")
pool = Pool(4)
pool.map(get_video,video_urls)

3.协程基本操作.

import asyncio
from time import sleep

#定义好了一个特殊的函数
async def get_request(url):
    print('正在请求:',url)
    sleep(2)
    print('请求成功:',url)
    return 'bobo'


#定义一个task的回调函数
def callback(task):
    print(' i am callback:',task.result())


#调用了特殊的函数,意味着该函数内部的实现语句不会被立即执行而是会返回一个协程对象
c = get_request('www.q.com')


#创建一个任务对象
task = asyncio.ensure_future(c)

#给任务对象绑定回调函数
task.add_done_callback(callback)

#创建事件循环对象
loop = asyncio.get_event_loop()
#将任务对象注册/装载到事件循环对象中,然后需要启动事件循环对象
loop.run_until_complete(task)

4.多任务操作.

import asyncio
from time import sleep
import time

start = time.time()
#定义好了一个特殊的函数
async def get_request(url):
    print('正在请求:',url)
    await asyncio.sleep(2)
    print('请求成功:',url)
    return 'bobo'

urls = [
    'http://localhost:5000/bobo',
    'http://localhost:5000/jay',
    'http://localhost:5000/tom'
]

tasks = [] #多个任务对象
for url in urls:
    c = get_request(url)
    task = asyncio.ensure_future(c)
    tasks.append(task)

loop = asyncio.get_event_loop()
#将任务列表注册到事件循环中的时候一定要将任务列表进行挂起操作
loop.run_until_complete(asyncio.wait(tasks))

print('总耗时:',time.time()-start)

5.多任务异步爬虫.

import asyncio
from time import sleep
import time
import requests
from lxml import etree
import aiohttp
urls = [
    'http://localhost:5000/bobo',
    'http://localhost:5000/jay',
    'http://localhost:5000/tom'
]
start = time.time()
#发起请求获取响应数据(不可以实现异步)
# async def get_request(url):
#     #requests是不支持异步的模块
#     page_text = requests.get(url).text
#     return page_text

#基于aiohttp实现异步的网络请求
async def get_request(url):
    #实例化了一个请求对象
    async with aiohttp.ClientSession() as sess:
        #with sess.get/post(url=url,headers=headers,data/params,proxy="http://ip:port") as response:
        async with await sess.get(url=url) as response:
            #text():获取字符串形式的响应数据
            #read():获取bytes类型的响应数据
            page_text = await response.text()

            return page_text

#定义回调函数
def parse(task):
    page_text = task.result()#获取特殊函数的返回值(请求到的页面源码数据)
    tree = etree.HTML(page_text)
    print(tree.xpath('//*[@id="feng"]/text()')[0])

tasks = []
for url in urls:
    c = get_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)

  • 线程池

    • 导包:from multiprocessing.dummy import Pool
    • pool.map(callback,alist)
      • 让callback可以异步将alist中的列表元素进行某种形式的操作
      • 注意事项:callback必须要有一个参数、
    • 主要是被应用在耗时的操作
  • 单线程+多任务的异步协程

    • 特殊函数

      • 如果一个函数的定义被async关键字修饰后,则该函数就是一个特殊的函数。
      • 特殊之处:
        • 该函数被调用后函数内部的实现语句不会被立即执行。
        • 该函数会返回一个协程对象
    • 协程:

      • 对象。当特殊的函数被调用后,该函数就会返回一个协程对象。
      • 协程对象 == 特殊函数
    • 任务对象

      • 就是对协程对象的进一步封装(就是一个高级的协程对象)
      • 任务对象协程对象特殊函数
      • 绑定回调:
        • task.add_done_callback(funcName)
        • funName这个回调函数必须要带一个参数,这个参数表示的就是当前的任务对象
          • 参数.result():表示的就是当前任务对象对应的特殊函数的返回值
    • 事件循环对象:

      • 创建事件循环对象
        • asyncio.get_event_loop()
      • 需要将任务对象注册到该事件循环对象中且启动事件循环
        • loop.run_until_complete(task)
    • 等待(await):当阻塞操作结束后让loop回头执行阻塞之后的代码

    • 挂起(wait()):将当前的任务对象交出cpu的使用权

    • 【重点注意事项】:

  • 在特殊函数实现内部不可以出现不支持异步的模块代码,否则会中断整个的异步效果

    • aiohttp:

      • requests不支持异步,不可以出现在特殊函数内部。

      • aiohttp:支持异步的网络请求模块

        • pip install aiohttp
      • 代码的编写:

        • 写出基本架构
          with aiohttp.ClientSession() as sess:
          #with sess.get/post(url=url,headers=headers,data/params,proxy="http://ip:port") as response:
          with sess.get(url=url) as response:
          #text():获取字符串形式的响应数据
          #read():获取bytes类型的响应数据
          page_text = response.text()

                  return page_text
          
        • 补充细节

          • 在每一个with前加上async
          • 在每一个阻塞操作前加上await关键字
            • 代码参照完整代码
      • 完整代码:
        async with aiohttp.ClientSession() as sess:

        with sess.get/post(url=url,headers=headers,data/params,proxy="http://ip:port") as response:

        async with await sess.get(url=url) as response:
        #text():获取字符串形式的响应数据

        read():获取bytes类型的响应数据

        page_text = await response.text()

         return page_text
        
  • 解析到带html标签的文本内容

    • bs4