Web自动化测试工具,可运行在浏览器,根据指令操作浏览器,只是工具,必须与第三方浏览器结合使用,相比于之前学的爬虫只是慢了一点而已。而且这种方法爬取的东西不用在意时候ajax动态加载等反爬机制。因此找标签可以直接F12找,不用确定源码中是否存在。

安装

Linux: sudo pip3 install selenium

Windows: python -m pip install selenium

phantomjs浏览器

phantomjs浏览器又叫做无界面浏览器(又称无头浏览器),在内存中进行页面加载,运行高效。

安装(phantomjs(无界面浏览器)、chromedriver(谷歌浏览器)、geckodriver(火狐浏览器))

Windows

1、下载对应版本的phantomjschromedrivergeckodriver

2、chromedriver下载与谷歌浏览器对应的版本,把chromedriver.exe拷贝到python安装目录的Scripts目录下(添加到系统环境变量),查看python安装路径: where python

3、验证,cmd命令行: chromedriver

Linux

1、下载后解压:tar -zxvf geckodriver.tar.gz

2、拷贝解压后文件到 /usr/bin/ (添加环境变量):sudo cp geckodriver /usr/bin/

3、更改权限

sudo -i

cd /usr/bin/

chmod 777 geckodriver

示例代码一:使用 selenium+谷歌浏览器 打开百度,并截图百度首页

from selenium import webdriver

browser = webdriver.Chrome()            # 创建浏览器对象
browser.get('http://www.baidu.com/') # 打开百度
browser.save_screenshot('baidu.png') # 截屏
browser.quit() # 退出浏览器

示例代码二:打开百度,搜索赵丽颖

from selenium import webdriver
import time # 创建浏览器对象 - 已经打开了浏览器
browser = webdriver.Chrome()
browser.get('http://www.baidu.com/') # 打开百度
ele = browser.find_element_by_xpath('//*[@id="kw"]') # 找到搜索框
ele.send_keys('赵丽颖') # 向搜索框发送文字: 赵丽颖 time.sleep(1)
# 找到 百度一下 按钮,点击一下
browser.find_element_by_xpath('//*[@id="su"]').click()
time.sleep(2)
browser.quit() # 关闭浏览器

browser浏览器对象方法

  • browser = webdriver.Chrome(executable_path='path')  path为浏览器驱动地址
  • browser.get(url)         打开path路径
  • browser.page_source:      查看响应内容(网页源代码)
  • browser.page_source.find('字符串'):从html源码中搜索指定字符串,没有找到返回:-1
  • browser.quit():关闭浏览器

元素查找

单元素查找(1个节点对象)

  1. browser.find_element_by_id('')
  2. browser.find_element_by_name('')
  3. browser.find_element_by_class_name('')
  4. browser.find_element_by_xpath('')
  5. browser.find_element_by_link_text('')
  6. ... ...

多元素查找([节点对象列表])

  1. browser.find_elements_by_id('')
  2. browser.find_elements_by_name('')
  3. browser.find_elements_by_class_name('')
  4. browser.find_elements_by_xpath('')
  5. ... ...

节点对象操作

  1. .send_keys('')     搜索框发送内容
  2. .click()        点击
  3. .text           获取文本内容
  4. .get_attribute('src') 获取属性值
  5. .find("")        查找响应中的字符串
from selenium import webdriver

browser = webdriver.Chrome()
browser.get('https://www.qiushibaike.com/text/') # 单元素查找
div = browser.find_element_by_class_name('content')
print(div.text) # 多元素查找: [<selenium xxx at xxx>,<selenium xxx >]
divs = browser.find_elements_by_class_name('content')
for div in divs:
print('*************************')
print(div.text)
print('*************************') browser.quit() # 退出浏览器

京东爬虫案例

目标网址 :https://www.jd.com/
抓取目标 :商品名称、商品价格、评价数量、商品商家

思路提醒

  1. 打开京东,到商品搜索页
  2. 匹配所有商品节点对象列表
  3. 把节点对象的文本内容取出来,查看规律,是否有更好的处理办法?
  4. 提取完1页后,判断如果不是最后1页,则点击下一页

实现步骤

找节点

  • 首页搜索框 : //*[@id="key"]
  • 首页搜索按钮   ://*[@id="search"]/div/div[2]/button
  • 商品页的 商品信息节点对象列表 ://*[@id="J_goodsList"]/ul/li

执行JS脚本,获取动态加载数据

  browser.execute_script('window.scrollTo(0,document.body.scrollHeight)')

from selenium import webdriver
import time class JdSpider(object):
def __init__(self):
self.i = 0
self.url = 'https://www.jd.com/'
self.browser = webdriver.Chrome() # 获取页面信息 - 到具体商品的页面
def get_html(self):
self.browser.get(self.url)
self.browser.find_element_by_xpath('//*[@id="key"]').send_keys('爬虫书') # 搜索框输入“爬虫书”
self.browser.find_element_by_xpath('//*[@id="search"]/div/div[2]/button').click() # 点击搜索
time.sleep(3) # 给商品页面加载时间 # 解析页面
def parse_html(self):
# 把下拉菜单拉到底部,执行JS脚本
self.browser.execute_script('window.scrollTo(0,document.body.scrollHeight)')
time.sleep(2)
# 提取所有商品节点对象列表 li列表
li_list = self.browser.find_elements_by_xpath('//*[@id="J_goodsList"]/ul/li')
for li in li_list:
info_list = li.text.split('\n')
if info_list[0].startswith('每满') or info_list[1].startswith('¥'):
price = info_list[1]
name = info_list[2]
comment = info_list[3]
shop = info_list[4]
elif info_list[0].startswith('单件'):
price = info_list[3]
name = info_list[4]
comment = info_list[5]
shop = info_list[6]
else:
price = info_list[0]
name = info_list[1]
comment = info_list[2]
shop = info_list[3] print(price, comment, shop, name) # 主函数
def main(self):
self.get_html()
while True:
self.parse_html()
# 判断是否该点击下一页,没有找到说明不是最后一页
if self.browser.page_source.find('pn-next disabled') == -1:
self.browser.find_element_by_class_name('pn-next').click()
time.sleep(2)
else:
break
print(self.i) if __name__ == '__main__':
spider = JdSpider()
spider.main()

chromedriver设置无界面模式

from selenium import webdriver

options = webdriver.ChromeOptions()   # 设置无界面
options.add_argument('--headless') # 添加无界面参数
browser = webdriver.Chrome(options=options)
browser.get('http://www.baidu.com/')
browser.save_screenshot('baidu.png')
browser.quit()

把上面的代码改为无界面模式

from selenium import webdriver
import time class JdSpider(object):
def __init__(self):
self.url = 'https://www.jd.com/'
self.options = webdriver.ChromeOptions() # 设置无界面
self.options.add_argument('--headless') # 添加无界面参数
# 正常创建浏览器对象即可
self.browser = webdriver.Chrome(options=self.options)
self.i = 0 # 统计商品数 # 获取页面信息 - 到具体商品的页面
def get_html(self):
self.browser.get(self.url)
self.browser.find_element_by_xpath('//*[@id="key"]').send_keys('爬虫书') # 搜索框输入“爬虫书”
self.browser.find_element_by_xpath('//*[@id="search"]/div/div[2]/button').click() # 点击搜索
time.sleep(3) # 给商品页面加载时间 def parse_html(self):
# 把进度条拉到底部,使所有数据动态加载
self.browser.execute_script('window.scrollTo(0,document.body.scrollHeight)')
time.sleep(2) # 等待动态数据加载完成 # 提取所有商品节点对象列表 li列表
li_list = self.browser.find_elements_by_xpath('//*[@id="J_goodsList"]/ul/li')
item = {}
for li in li_list:
# find_element: 查找单元素
item['name'] = li.find_element_by_xpath('.//div[@class="p-name"]/a/em').text.strip()
item['price'] = li.find_element_by_xpath('.//div[@class="p-price"]').text.strip()
item['comment'] = li.find_element_by_xpath('.//div[@class="p-commit"]/strong').text.strip()
item['shop'] = li.find_element_by_xpath('.//div[@class="p-shopnum"]').text.strip() print(item)
self.i += 1 def main(self):
self.get_html()
while True:
self.parse_html()
# 判断是否为最后一页
if self.browser.page_source.find('pn-next disabled') == -1:
self.browser.find_element_by_class_name('pn-next').click()
time.sleep(3)
else:
break
print('商品数量:', self.i)
self.browser.quit() if __name__ == '__main__':
spider = JdSpider()
spider.main()

键盘操作

from selenium.webdriver.common.keys import Keys

browser = webdriver.Chrome()
browser.get('http://www.baidu.com/')
# 1、在搜索框中输入"selenium"
browser.find_element_by_id('kw').send_keys('赵丽颖')
# 2、输入空格
browser.find_element_by_id('kw').send_keys(Keys.SPACE)
# 3、Ctrl+a 模拟全选
browser.find_element_by_id('kw').send_keys(Keys.CONTROL, 'a')
# 4、Ctrl+c 模拟复制
browser.find_element_by_id('kw').send_keys(Keys.CONTROL, 'c')
# 5、Ctrl+v 模拟粘贴
browser.find_element_by_id('kw').send_keys(Keys.CONTROL, 'v')
# 6、输入回车,代替 搜索 按钮
browser.find_element_by_id('kw').send_keys(Keys.ENTER)

鼠标操作

import time
from selenium import webdriver
# 导入鼠标事件
from selenium.webdriver import ActionChains browser = webdriver.Chrome()
browser.get('http://www.baidu.com/') # 找到“设置”节点
element = browser.find_element_by_xpath('//*[@id="u1"]/a[8]') # 把鼠标移动到 设置 节点,move_to_element()
actions = ActionChains(browser)
actions.move_to_element(element)
actions.perform() # perform()是真正执行操作
time.sleep(1)
# 找到高级设置节点,并点击
browser.find_element_by_link_text('高级搜索').click()

切换页面

适用与页面中点开链接出现新的页面的网站,但是浏览器对象browser还是之前页面的对象

all_handles = browser.window_handles  获取当前所有句柄(窗口)

browser.switch_to_window(all_handles[1])  切换browser到新的窗口,获取新窗口对象

民政部网站

将民政区划代码爬取到数据库中,按照层级关系(分表 -- 省表、市表、县表)

数据库中建表

# 建库
create database govdb charset utf8;
use govdb;
# 建表
create table province(
p_name varchar(20),
p_code varchar(20)
)charset=utf8;
create table city(
c_name varchar(20),
c_code varchar(20),
c_father_code varchar(20)
)charset=utf8;
create table county(
x_name varchar(20),
x_code varchar(20),
x_father_code varchar(20)
)charset=utf8;

思路

  1. selenium+Chrome打开一级页面,并提取二级页面最新链接
  2. 增量爬取: 和数据库version表中进行比对,确定之前是否爬过(是否有更新)
  3. 如果没有更新,直接提示用户,无须继续爬取
  4. 如果有更新,则删除之前表中数据,重新爬取并插入数据库表
  5. 最终完成后: 断开数据库连接,关闭浏览器
from selenium import webdriver
import pymysql class GovSpider(object):
def __init__(self):
# 设置无界面
options = webdriver.ChromeOptions()
options.add_argument('--headless')
self.browser = webdriver.Chrome(options=options) # 添加参数
self.one_url = 'http://www.mca.gov.cn/article/sj/xzqh/2019/'
# 创建数据库和相关变量
self.db = pymysql.connect('localhost', 'root', '', 'govdb', charset='utf8')
self.cursor = self.db.cursor()
# 创建3个列表,用来executemany()往3张表中插入记录
self.province_list = []
self.city_list = []
self.county_list = [] # 获取首页,并提取二级页面链接(虚假链接)
def get_incr_url(self):
self.browser.get(self.one_url)
# 提取最新链接,判断是否需要增量爬
td = self.browser.find_element_by_xpath('//td[@class="arlisttd"]/a[contains(@title,"代码")]')
# 提取链接 和 数据库中做比对,确定是否需要怎俩那个抓取
# get_attribute()会自动补全提取的链接
two_url = td.get_attribute('href')
# result为返回的受影响的条数
result = self.cursor.execute('select url from version where url=%s', [two_url])
if result:
print('无须爬取')
else:
td.click()
# 切换句柄
all_handlers = self.browser.window_handles
self.browser.switch_to.window(all_handlers[1])
self.get_data() # 数据抓取
# 把URL地址存入version表
self.cursor.execute('delete from version')
self.cursor.execute('insert into version values(%s)', [two_url])
self.db.commit() # 二级页面中提取行政区划代码
def get_data(self):
# 基准xpath
tr_list = self.browser.find_elements_by_xpath('//tr[@height="19"]')
for tr in tr_list:
code = tr.find_element_by_xpath('./td[2]').text.strip()
name = tr.find_element_by_xpath('./td[3]').text.strip()
print(name, code)
# 判断层级关系,添加到对应的数据库表中(对应表中字段)
# province: p_name p_code
# city : c_name c_code c_father_code
# county : x_name x_code x_father_code # 把数据添加到对应的表中
if code[-4:] == '':
self.province_list.append([name, code])
if name in ['北京市', '天津市', '上海市', '重庆市']:
self.city_list.append([name, code, code]) elif code[-2:] == '':
self.city_list.append([name, code, (code[:2] + '')]) else:
if code[:2] in ['', '', '', '']:
self.county_list.append([name, code, (code[:2] + '')])
else:
self.county_list.append([name, code, (code[:4] + '')]) # # 和for循环同缩进,所有数据爬完后统一excutemany(),
# 执行数据库插入语句
self.insert_mysql() def insert_mysql(self):
# 1. 更新时一定要先删除表记录
self.cursor.execute('delete from province')
self.cursor.execute('delete from city')
self.cursor.execute('delete from county')
# 2. 插入新数据
self.cursor.executemany('insert into province values(%s,%s)', self.province_list)
self.cursor.executemany('insert into city values(%s,%s,%s)', self.city_list)
self.cursor.executemany('insert into county values(%s,%s,%s)', self.county_list)
# 3.提交到数据库执行
self.db.commit()
print('数据抓取完成,成功存入数据库') def main(self):
self.get_incr_url()
self.cursor.close() # 所有数据处理完成后断开连接
self.db.close()
self.browser.quit() # 关闭浏览器 if __name__ == '__main__':
spider = GovSpider()
spider.main()

SQL命令练习

1. 查询所有省市县信息(多表查询实现)

select province.p_name,city.c_name,county.x_name from province,city,county  where province.p_code=city.c_father_code and city.c_code=county.x_father_code;

2. 查询所有省市县信息(连接查询实现)

select province.p_name,city.c_name,county.x_name from province inner join city on province.p_code=city.c_father_code inner join county on city.c_code=county.x_father_code;

Web客户端验证

在URL地址中填入即可

url = 'http://用户名:密码@正常地址'

示例: 爬取某一天笔记

from selenium import webdriver

url = 'http://tarenacode:code_2013@code.tarena.com.cn/AIDCode/aid1904/15-spider/spider_day06_note.zip'
browser = webdriver.Chrome()
browser.get(url)

iframe子框架

iframe子框架适用于网页中嵌套了网页,这种情况应该先切换到iframe子框架,然后再执行其他操作。

browser.switch_to.iframe(iframe_element)

示例 - 登录qq邮箱

import time
from selenium import webdriver browser = webdriver.Chrome()
browser.get('https://mail.qq.com/cgi-bin/loginpage') # 找iframe子框架并切换到此iframe
login_frame = browser.find_element_by_id('login_frame')
browser.switch_to.frame(login_frame) # qq+密码+登录
browser.find_element_by_id('u').send_keys('账号')
browser.find_element_by_id('p').send_keys('密码')
browser.find_element_by_id('login_button').click() time.sleep(5) # 预留页面记载时间 # 提取数据
ele = browser.find_element_by_id('useralias')
print(ele.text)

selenium爬虫的更多相关文章

  1. Python爬虫之selenium爬虫,模拟浏览器爬取天猫信息

    由于工作需要,需要提取到天猫400个指定商品页面中指定的信息,于是有了这个爬虫.这是一个使用 selenium 爬取天猫商品信息的爬虫,虽然功能单一,但是也算是 selenium 爬虫的基本用法了. ...

  2. python爬虫---单线程+多任务的异步协程,selenium爬虫模块的使用

    python爬虫---单线程+多任务的异步协程,selenium爬虫模块的使用 一丶单线程+多任务的异步协程 特殊函数 # 如果一个函数的定义被async修饰后,则该函数就是一个特殊的函数 async ...

  3. 爬虫(十一):selenium爬虫

    1. selenium基础 selenium部分可以去看我写的selenium基础部分,由于链接太多了这里就不发出来了. 代理ip: 有时候频繁爬取一些网页.服务器发现你是爬虫后会封掉你的ip地址.这 ...

  4. Selenium爬虫实践(踩坑记录)之ajax请求抓包、浏览器退出

    上一篇: 使用Selenium截取网页上的图片 前言 最近在搞公司内部系统,累的一批,需要从另一个内部系统导出数据存到数据库做分析,有大量的数据采集工作,又没办法去直接拿到那个系统的接口,太难了,只能 ...

  5. Ubuntu下的Selenium爬虫的配置

    在服务器Ubuntu系统上跑爬虫,爬虫是基于Selenium写的,遇到好几个问题,现在这里记录一下. 1. 安装环境 阿里云,Ubuntu16.04,因为没有界面,所以远程命令行操作.爬虫是基于Sel ...

  6. Katalon Recorder 自动录制 Selenium 爬虫脚本

    相信很多小伙伴都用过 Selenium 来完成爬虫工作,今天就给大家带来一个神器,可以录制你的浏览器动作,然后直接生成 Selenium 脚本,是不是心动了? 1 Selenium 简介 Seleni ...

  7. 使用selenium爬虫抓取数据

    写在前面 本来这篇文章该几个月前写的,后来忙着忙着就给忘记了.ps:事多有时候反倒会耽误事.几个月前,记得群里一朋友说想用selenium去爬数据,关于爬数据,一般是模拟访问某些固定网站,将自己关注的 ...

  8. selenium爬虫入门(selenium+Java+chrome)

    selenium是一个开源的测试化框架,可以直接在浏览器中运行,就像用户直接操作浏览器一样,十分方便.它支持主流的浏览器:chrome,Firefox,IE等,同时它可以使用Java,python,J ...

  9. python selenium爬虫工具

    今天seo的同事需要一个简单的爬虫工具, 根据一个url地址,抓取改页面的a连接,然后进入a连接里面的页面再次抓取a连接 1.需要一个全局的set([])集合来保存抓取的url地址 2.由于现在单页面 ...

随机推荐

  1. 二叉查找树(查找、插入、删除)——C语言

    二叉查找树 二叉查找树(BST:Binary Search Tree)是一种特殊的二叉树,它改善了二叉树节点查找的效率.二叉查找树有以下性质: (1)若左子树不空,则左子树上所有节点的值均小于它的根节 ...

  2. (一)Mybatis基本配置,Statement方式,动态代理增删改查

    首先明白Mybatis是干什么的,之前使用jdbc操作数据库时候要写很多语句,获取光标,连接,获取具体对象进行相应操作,代码过于繁琐,所以现在有了Mybatis,它将这个操作整合在了一起,你不需要关心 ...

  3. 佳木斯集训Day1

    23333第一次写博客 其实在佳木斯集训之前我都已经两三个月没打代码了 在佳木斯的时候前几天真心手生,导致了前几次考试考的很差... D1的考试还是比较良心的,T1是一道大模拟,直接枚举最后几位是00 ...

  4. 高性能MySQL之基础架构

    一.背景 为什么我们需要先学习MYSQL的基础架构先呢? 原因很简单,当我们需要了解一件事物的时候,我们只有站在宏观的层面,才能层层剥丝抽茧的去理解问题.举个例子,我们要看一个框架的源码,一开始就想进 ...

  5. 转载 | 如何给网页标题添加icon小图标

    打开某一个网页会在浏览器的标签栏处显示该网页的标题和图标,当网页被添加到收藏夹或者书签中时也会出现网页的图标,怎么在网页title左边显示网页的logo图标呢? 方法一(被动式): 制作一个ico格式 ...

  6. Kafka 0.8 Producer (0.9以前版本适用)

    Kafka旧版本producer由scala编写,0.9以后已经废除,但是很多公司还在使用0.9以前的版本,所以总结如下: 要注意包Producer是 kafka.javaapi.producer.P ...

  7. ‎Cocos2d-x 学习笔记(21) ScrollView (CCScrollView)

    1. 简介 CCScrollView.cpp文件内的滚动视图ScrollView直接继承了Layer+ActionTweenDelegate. 滚动视图能在屏幕区域内,用户通过触摸拖动屏幕,实现大于屏 ...

  8. 如何让springboot打包的项目部署在阿里云上使用https和http方式访问

    前言 问题描述:怎么让springboot部署在服务器上使用https协议方式访问我们的接口或者域名,目的是某些平台请求的是https协议,而不是https 部署环境:阿里云 centos7服务器,s ...

  9. python paramiko外部传参和内部调用命令的方法

    学习了很久的python,但在工作中使用的时候,却发现不知道怎么传参进入到python中执行,所以这两天就研究 了python args怎么将外部参数传入到python中执行 1.首先使用python ...

  10. odoo项目结构参数属性详解

    1.基础文件及目录结构 在认识odoo ORM框架前,先介绍一下odoo中模块目录结构.   data:存放模块预制数据i18n:存放国际化文件models:存放模型等py代码security:存放权 ...