from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get('https://music.163.com/#/song?id=1450083773')
"""切换进入到嵌套网页有两种方法"""
# 方式1
# frame(0) 根据索引进入到嵌套网页, 索引从0开始, 索引的值不能超过当前网页已有的嵌套网页数量
# driver.switch_to.frame(0)
# 方式2
iframe_label = driver.find_element(By.CSS_SELECTOR, '#g_iframe')
driver.switch_to.frame(iframe_label)
driver.switch_to.parent_frame() # 从嵌套网页切换到父级网页
print(driver.page_source)
input()
driver.quit()
"""
如果当前网页有好几层嵌套结构, 那么需要一层一层进入, 退出也要一层一层退出
div + css
嵌套网页常见于注册或者登录的区域
后续用selenium操作任何一个网页, 首先第一步就是要查看网页有没有嵌套结构
"""
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get('https://www.douban.com/')
# document.documentElement.scrollTop 指定滚动条的位置
# document.documentElement.scrollHeight 获取当前页面的最大高度
js = 'document.documentElement.scrollTop=3000'
js_all = 'document.documentElement.scrollTop = document.documentElement.scrollHeight'
driver.execute_script(js_all)
input()
driver.quit()
import csv
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
def search_product(key):
"""指定关键字搜索商品"""
# 找到搜索框输入商品关键字
driver.find_element(By.CSS_SELECTOR, '#key').send_keys(key)
# 点击搜索按钮
driver.find_element(By.CSS_SELECTOR, '.button>i').click()
def drop_down():
"""实现页面的下拉操作"""
# js_all = 'document.documentElement.scrollTop = document.documentElement.scrollHeight'
# driver.execute_script(js_all)
for i in range(1, 10, 2): # 13579
j = i / 14 # 1/9 3/9 5/9 7/9 9/9
js_all = 'document.documentElement.scrollTop = document.documentElement.scrollHeight*%f' % j
driver.execute_script(js_all)
time.sleep(0.5) # 给一定的时间渲染加载数据
def parse_data():
"""解析数据函数"""
lis = driver.find_elements(By.CSS_SELECTOR, '.gl-item')
for li in lis:
try:
title = li.find_element(By.CSS_SELECTOR, 'div.p-name>a>em').text # 商品名字
title = title.replace('京品电脑', '').replace('京东超市', '').replace('\n', '')
price = li.find_element(By.CSS_SELECTOR, 'div.p-price>strong>i').text # 价格
deal = li.find_element(By.CSS_SELECTOR, 'div.p-commit>strong>a').text # 评论数量
name = li.find_element(By.CSS_SELECTOR, 'span.J_im_icon>a').text # 店铺名字
print(title, price, deal, name, sep=' | ')
with open('某东.csv', mode='a', encoding='utf-8', newline='') as f:
csv_write = csv.writer(f)
csv_write.writerow([title, price, deal, name])
except Exception as e:
print(e)
def get_next():
"""点击下一页"""
driver.find_element(By.CSS_SELECTOR, '.pn-next>em').click()
if __name__ == '__main__':
word = input('请输入你那药搜索商品的关键字:')
driver = webdriver.Chrome()
driver.get('https://www.jd.com/')
driver.implicitly_wait(10)
driver.maximize_window()
# 调用商品搜索功能函数
search_product(word)
for i in range(100):
time.sleep(1)
# 调用页面下拉函数
drop_down()
# 调用解析数据函数
parse_data()
# 点击下一页
get_next()
input()
driver.quit()
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains # 导入鼠标动作链对象
driver = webdriver.Chrome()
driver.get('https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
# 进入嵌套网页
driver.switch_to.frame(0)
# 找到可以拖动的标签
drag = driver.find_element(By.CSS_SELECTOR, '#draggable')
# 找到需要放置的标签
drop = driver.find_element(By.CSS_SELECTOR, '#droppable')
"""动作链对象操作"""
# 以下是分开写的, 后续可以直接链式调用
# 1. 实例化动作链对象, 括号内部需要传递当前driver浏览器对象
action = ActionChains(driver)
# 2. 编排一个鼠标动作, 但是这个动作还没执行
action.drag_and_drop(drag, drop)
# 3. 执行动作
action.perform()
input()
driver.quit()
"""
消息提示框和弹窗
"""
import time
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get('https://gitee.com/')
driver.implicitly_wait(10)
driver.maximize_window()
driver.find_element(By.LINK_TEXT, '登录').click()
driver.find_element(By.CSS_SELECTOR, '#git-login>input').send_keys('输入的用户名')
time.sleep(2)
driver.find_element(By.CSS_SELECTOR, '#user_password').send_keys('输入的密码')
time.sleep(2)
driver.find_element(By.NAME, 'commit').click()
""" 处理消息提示框 """
# time.sleep(3)
# context_click 确定位置, click坐标点击
# ActionChains(driver).move_by_offset(200, 200).context_click().perform()
# ActionChains(driver).move_by_offset(1047, 370).context_click().perform()
ActionChains(driver).move_by_offset(1047, 370).click().perform()
input()
driver.quit()
# 在百度搜索框输入 python ,全选,复制,剪切,粘贴 跳转到搜狗输入框进行搜索
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys # 键盘事件功能
driver = webdriver.Chrome()
driver.get('https://www.baidu.com/')
driver.find_element(By.CSS_SELECTOR, '#kw').send_keys('python')
time.sleep(3)
driver.find_element(By.CSS_SELECTOR, '#kw').send_keys(Keys.CONTROL, 'a') # 全选
time.sleep(3)
driver.find_element(By.CSS_SELECTOR, '#kw').send_keys(Keys.CONTROL, 'c') # 复制
time.sleep(3)
driver.find_element(By.CSS_SELECTOR, '#kw').send_keys(Keys.CONTROL, 'x') # 复制
time.sleep(3)
driver.get('https://www.sogou.com/')
driver.find_element(By.CSS_SELECTOR, '#query').send_keys(Keys.CONTROL, 'v') # 粘贴
# 按回车键搜索
driver.find_element(By.CSS_SELECTOR, '#stb').send_keys(Keys.ENTER)
input()
driver.quit()
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.select import Select # 下拉框功能
driver = webdriver.Chrome()
driver.get('https://www.jq22.com/demo/shengshiliandong/')
# 找下拉框对应的
element = driver.find_element(By.CSS_SELECTOR, '#s_province')
# 实例化对象
select = Select(element)
# 选择下拉框
# 1.根据索引取下拉框, 索引从1开始
select.select_by_index(1) # 北京市
time.sleep(2)
# 2.根据下拉框value属性值选择
select.select_by_value('河北省') # 河北省
time.sleep(2)
# 3.根据下拉框标签包含的文本选择
select.select_by_visible_text('湖北省') # 湖北省
time.sleep(2)
input()
driver.quit()
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains # 导入鼠标动作链对象
driver = webdriver.Chrome()
driver.get('https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
driver.switch_to.frame(0)
drag = driver.find_element(By.CSS_SELECTOR, '#draggable')
drop = driver.find_element(By.CSS_SELECTOR, '#droppable')
action = ActionChains(driver)
action.drag_and_drop(drag, drop)
action.perform()
"""处理弹窗"""
ert = driver.switch_to.alert # 切换到弹窗
print(ert.text)
ert.accept()
input()
driver.quit()
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains # 导入鼠标动作链对象
from selenium.webdriver.chrome.options import Options # 导入谷歌浏览器的配置选项
options = Options() # 实例化配置对象
options.add_argument('--headless') # 添加无头模式配置
driver = webdriver.Chrome(options=options)
driver.get('https://www.baidu.com/')
print(driver.page_source)
input()
driver.quit()
"""
selenium的无头模式一般用于项目写完以后添加, 因为我们在写selenium项目的时候需要看页面效果
优点:
相对有界面的情况下, 获取数据的速度更加快, 原因是因为无头模式没有启动浏览器GUI, 没有加载css js 特效
"""
现在不少大网站有对selenium采取了监测机制。比如正常情况下我们用浏览器访问淘宝等网站的 window.navigator.webdriver的值为 undefined或者为false。而使用selenium访问则该值为true。那么如何解决这个问题呢?
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains # 导入鼠标动作链对象
from selenium.webdriver.chrome.options import Options # 导入谷歌浏览器的配置选项
driver = webdriver.Chrome()
# 绕过检测的代码要放到实例化浏览器对象下面
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source": """
Object.defineProperty(navigator, 'webdriver', {
get: () => false
})
"""
})
driver.get('https://antispider1.scrape.center')
print(driver.page_source)
input()
driver.quit()
"""
在人机检测的时候比较有效果
不是所有的检测方式都可以这样解决
可以通过代码接管已经打开的真实的浏览器
"""
"""
目标网址:https://music.163.com/#/playlist?id=924680166
要求:
1. 使用selenium
2. 爬取前面5页的评论数据保存为txt文件
"""
import time
import parsel
from selenium.webdriver.chrome.options import Options
from selenium import webdriver
from selenium.webdriver.common.by import By
def parse_data():
"""解析评论数据保存"""
divs = driver.find_elements(By.CSS_SELECTOR, '.itm')
print(divs)
for div in divs:
contend = div.find_element(By.CSS_SELECTOR, '.cnt.f-brk').text
contend = contend.replace('\n', '')
print('contend:', contend)
with open('contend.txt', mode='a', encoding='utf-8') as f:
f.write(contend)
if __name__ == '__main__':
options = Options()
options.add_experimental_option("excludeSwitches", ['enable-automation']) # 禁用正在收到自动测试软件的控制
driver = webdriver.Chrome(options=options)
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source": """
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
})
"""
})
driver.get('https://music.163.com/#/playlist?id=924680166')
driver.implicitly_wait(10)
driver.switch_to.frame(0)
js = 'document.documentElement.scrollTop = document.documentElement.scrollHeight'
driver.execute_script(js)
print(driver.page_source)
for i in range(5):
# 调用解析函数
parse_data()
driver.find_element(By.CSS_SELECTOR, '.znxt').click() # 点击下一页
time.sleep(2)
input()
driver.quit()
# 目标网址: https://www.wjx.cn/jq/87910206.aspx
import random
# 需求: 单选题随机选一项, 多选题随机选3项
import time
import parsel
from selenium.webdriver.chrome.options import Options
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source": """
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
})
"""
})
driver.get('https://www.wjx.cn/jq/87910206.aspx')
driver.implicitly_wait(10)
divs = driver.find_elements(By.CSS_SELECTOR, '.div_question')
print(divs)
print(len(divs)) #
"""
单选题: 1-10
多选题: 11-12
"""
one_choice = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] # 单选题的索引
any_choice = [10, 11] # 多选题的索引
# 先解决单选
for i in one_choice:
lis = divs[i].find_elements(By.CSS_SELECTOR, 'ul li')
# 随机选择一项
random.choice(lis).click()
# 解决多选
for j in any_choice:
lis = divs[j].find_elements(By.CSS_SELECTOR, 'ul li')
# 随机选择三项
# random.choice(lis).click() 随机单个
# random.choices() # 选择的多个选项可能会重复
lis_ = random.sample(lis, k=3) # random.sample 在序列中随机选择不同的选项
for h in lis_:
h.click()
# 点击提交
driver.find_element(By.CSS_SELECTOR, '#submit_button').click()
time.sleep(1)
# 点击人机校验
driver.find_element(By.CSS_SELECTOR, '.sm-ico-wave').click()
input()
driver.quit()
异步的selenium
。在 Pyppetter的背后是有一个类似 Chrome 浏览器的 Chromium 浏览器在执行一些动作进行网页渲染,首先说下 Chrome 浏览器和 Chromium 浏览器的渊源。
Chromium 是谷歌为了研发 Chrome 而启动的项目,是完全开源的。二者基于相同的源代码构建,Chrome 所有的新功能都会先在 Chromium 上实现,待验证稳定后才会移植,因此 Chromium 的版本更新频率更高,也会包含很多新的功能,但作为一款独立的浏览器,Chromium 的用户群体要小众得多。两款浏览器“同根同源”,它们有着同样的 Logo,但配色不同,Chrome 由蓝红绿黄四种颜色组成,而 Chromium 由不同深度的蓝色构成。
Pyppeteer 就是依赖于 Chromium 这个浏览器来运行的。那么有了 Pyppeteer 之后,我们就可以免去那些繁琐的环境配置等问题。如果第一次运行的时候,Chromium 浏览器没有安装,那么程序会帮我们自动安装和配置,就免去了繁琐的环境配置等工作。另外 Pyppeteer 是基于 Python 的新特性 async 实现的,所以它的一些执行也支持异步操作,效率相对于 Selenium 来说也提高了。
import asyncio
from pyppeteer import launch
from lxml import etree
# 第一次运行程序,会给你安装Chromium这个浏览器,因此运行时间会比较久
async def main():
browser = await launch(headless=False) # headless=True 表示使用无头模式
page = await browser.newPage()
await page.goto('http://quotes.toscrape.com/js/')
page_text = await page.content()
tree = etree.HTML(page_text)
div_list = tree.xpath('//div[@class="quote"]')
print(len(div_list))
await asyncio.sleep(3)
await browser.close()
c = main()
loop = asyncio.get_event_loop()
loop.run_until_complete(c)
代码解释:
解释:launch 方法会新建一个 Browser 对象,然后赋值给 browser,然后调用 newPage 方法相当于浏览器中新建了一个选项卡,同时新建了一个 Page 对象。然后 Page 对象调用了 goto 方法就相当于在浏览器中输入了这个 URL,浏览器跳转到了对应的页面进行加载,加载完成之后再调用 content 方法,返回当前浏览器页面的源代码。在这个过程中,我们没有配置 Chrome 浏览器,没有配置浏览器驱动,免去了一些繁琐的步骤,同样达到了 Selenium 的效果,还实现了异步抓取,爽歪歪!
browser = await launch(headless=False, args=['--disable-infobars'])
import asyncio
from pyppeteer import launch
async def main():
# 创建一个浏览器对象
browser = await launch(headless=False)
# 创建一个 page
page = await browser.newPage()
# 发起请求
await page.goto('https://www.taobao.com')
await asyncio.sleep(3)
await browser.close()
asyncio.get_event_loop().run_until_complete(main())
发现页面显示出现了问题,需要手动调用setViewport方法设置显示页面的长宽像素。设置如下:
import asyncio
from pyppeteer import launch
async def main():
# 创建一个浏览器对象
browser = await launch(headless=False)
# 创建一个 page
page = await browser.newPage()
# 可以专门设置打开page 的像素宽度和高度
await page.setViewport({'width': 1366, 'height': 1440})
# 发起请求
await page.goto('https://www.taobao.com')
await asyncio.sleep(3)
await browser.close()
asyncio.get_event_loop().run_until_complete(main())
执行js程序:拖动滚轮。调用evaluate方法
import asyncio
from pyppeteer import launch
async def main():
# 创建一个浏览器对象
browser = await launch(headless=False)
# 创建一个 page
page = await browser.newPage()
# 可以专门设置打开page 的像素宽度和高度
await page.setViewport({'width': 1366, 'height': 1440})
# 发起请求
await page.goto('https://www.taobao.com')
await asyncio.sleep(3)
# 执行JS代码
await page.evaluate('window.scrollTo(0,document.body.scrollHeight)')
await browser.close()
asyncio.get_event_loop().run_until_complete(main())
正常情况下我们用浏览器访问淘宝等网站的 window.navigator.webdriver的值为 undefined或者为false。而使用pyppeteer访问则该值为true。那么如何解决这个问题呢?
import asyncio
from pyppeteer import launch
width, height = 1366, 768
async def main():
# 规避检测
browser = await launch(headless=False, args=['--disable-infobars'])
page = await browser.newPage()
await page.setViewport({'width': width, 'height': height})
await page.goto('https://login.taobao.com/member/login.jhtml?redirectURL=https://www.taobao.com/')
# 规避检测
await page.evaluate(
'''() =>{ Object.defineProperties(navigator,{ webdriver:{ get: () => false } }) }''')
await asyncio.sleep(20)
await browser.close()
asyncio.get_event_loop().run_until_complete(main())
import asyncio
from pyppeteer import launch
async def main():
# headless参数设为False,则变成有头模式
browser = await launch(
headless=False,
# 指定任意的浏览器:chrome://version
executablePath='C:\Program Files\Google\Chrome\Application\chrome.exe'
)
page = await browser.newPage()
# 设置页面视图大小
await page.setViewport(viewport={'width': 1280, 'height': 800})
await page.goto('https://www.baidu.com/')
# 规避检测
await page.evaluate(
'''() =>{ Object.defineProperties(navigator,{ webdriver:{ get: () => false } }) }''')
# 节点交互:更好的模拟人的行为
await page.type('#kw', '周杰伦', {'delay': 2000})
await asyncio.sleep(3)
# 点击搜索按钮
await page.click('#su')
await asyncio.sleep(3)
# 使用选择器选中标签进行点击
alist = await page.querySelectorAll('.s_tab_inner > a')
a = alist[3]
await a.click()
await asyncio.sleep(3)
await browser.close()
asyncio.get_event_loop().run_until_complete(main())
'''
异步爬取网易新闻首页的新闻标题
- https://news.163.com/domestic/
- https://news.163.com/world/
- https://war.163.com/
'''
import asyncio
from pyppeteer import launch
from lxml import etree
async def get_data(url):
# headless参数设为False,则变成有头模式
browser = await launch(
headless=False,
# 可在浏览器中输入chrome://version/,在页面的"个人资料路径"查看浏览器的执行程序
executablePath='C:\Program Files\Google\Chrome\Application\chrome.exe'
)
page = await browser.newPage()
await page.goto(url)
await asyncio.sleep(3)
page_text = await page.content()
await browser.close()
return page_text
def parse(task):
page_text = task.result()
tree = etree.HTML(page_text)
div_list = tree.xpath('//div[@class="data_row news_article clearfix "]')
for div in div_list:
title = div.xpath('.//div[@class="news_title"]/h3/a/text()')[0]
print(title)
urls = ['https://news.163.com/domestic/',
'https://news.163.com/world/',
'https://war.163.com/']
tasks = []
for url in urls:
c = get_data(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))
import random
from pyppeteer import launch
import asyncio
import cv2
from urllib import request
async def get_track():
background = cv2.imread("background.png", 0)
gap = cv2.imread("gap.png", 0)
res = cv2.matchTemplate(background, gap, cv2.TM_CCOEFF_NORMED)
value = cv2.minMaxLoc(res)[2][0]
print(value)
return value * 278 / 360
async def main():
browser = await launch({
# headless指定浏览器是否以无头模式运行,默认是True。
"headless": False,
# 设置窗口大小
"args": ['--window-size=1366,768'],
})
# 打开新的标签页
page = await browser.newPage()
# 设置页面大小一致
await page.setViewport({"width": 1366, "height": 768})
# 访问主页
await page.goto("https://passport.jd.com/new/login.aspx?")
# 单击事件
await page.click('div.login-tab-r')
# 模拟输入用户名和密码,输入每个字符的间隔时间delay ms
await page.type("账号", '密码', {
"delay": random.randint(30, 60)
})
await page.type("#nloginpwd", '345653332', {
"delay": random.randint(30, 60)
})
# page.waitFor 通用等待方式,如果是数字,则表示等待具体时间(毫秒): 等待2秒
await page.waitFor(2000)
await page.click("div.login-btn")
await page.waitFor(2000)
# page.jeval(selector,pageFunction)#定位元素,并调用js函数去执行
# =>表示js的箭头函数:el = function(el){return el.src}
img_src = await page.Jeval(".JDJRV-bigimg > img", "el=>el.src")
temp_src = await page.Jeval(".JDJRV-smallimg > img", "el=>el.src")
request.urlretrieve(img_src, "background.png")
request.urlretrieve(temp_src, "gap.png")
# 获取gap的距离
distance = await get_track()
"""
# Pyppeteer 三种解析方式
Page.querySelector() # 选择器
Page.querySelectorAll()
Page.xpath() # xpath 表达式
# 简写方式为:
Page.J(), Page.JJ(), and Page.Jx()
"""
# 定位到滑动按钮标签
el = await page.J("div.JDJRV-slide-btn")
# 获取元素的边界框,包含x,y坐标
box = await el.boundingBox()
# box={'x': 86, 'y': 34, 'width': 55.0, 'height': 55.0}
# 将鼠标悬停/一定到指定标签位置
await page.hover("div.JDJRV-slide-btn")
# 按下鼠标
await page.mouse.down()
# 模拟人的行为进行滑动
# steps 是指分成几步来完成,steps越大,滑动速度越慢
# move(x,y)表示将鼠标移动到xy坐标位置
# random.uniform生成一个在指定范围内的随机浮点数
await page.mouse.move(box["x"] + distance + random.uniform(10, 30),
box["y"], {"steps": 100})
await page.waitFor(1000)
await page.mouse.up()
await page.waitFor(2000)
loop = asyncio.get_event_loop()
loop.run_until_complete(main())