自己学习selenium过程做的一些笔记,大部分都是讲课的内容,以及百度收集整合得到的
文章目录
京东物品详情页的物品价格,发现requests不能获取价格,说明是Ajax加载出来的内容使用page_source和etree配合后可以抓取这样的内容
from selenium import webdriver
import time
from lxml import etree
url="http://xxxxxxx.com"
browser=webdriver.Chrome()
browser.get(url)
time.sleep(10)
text=browser.page_source
browser.close()
tree=etree.HTML(text)
m=tree.xpath('//*[@id="J_StrPriceModBox"]/dd/span/text()')[0]
print(m)
1.webdriver.Chrome()
实例化一个浏览器对象 browser = webdriver.Chrome()
selenium支持很多游览器,如Chrome,Firefox,Opera和Edge等,还支持Andriod,BlackBerry等手机端的游览器,另外还支持无界面游览器PhantomJS。
webdriver.Chrome()方法的executable_path参数设置chromedriver.exe的路径,而不是chrome.exe的路径。
2.get
这里的get让浏览器发起一个指定url对应请求
3.page_source
虽然有些通过ajax动态渲染出来的页面通过对请求链接的分析我们仍然可以使用urllib或requests库来进行数据爬取,但javascript动态渲染页面的方式不止ajax一种,如echart官网的许多图表都是经过javascript执行特定算法生成的,且对于淘宝这种页面,其ajax请求中含有很多加密参数,我们也很难直接分析出它的规律。
为了解决这些问题,我们可以直接使用模拟浏览器运行的方式来实现,这样就可以做到在浏览器中看到是什么样,抓取的源码就是什么样,也就是可见即可爬。这样我们就不用再去管网页内部的JavaScript用了什么算法渲染页面,不用管网页后台的Ajax接口到底有哪些参数。
4.查找节点的几种方法
通过id定位元素: find_element_by_id(“id_vaule”)
通过name定位元素: find_element_by_name(“name_vaule”)
通过tag_name定位元素: find_element_by_tag_name(“tag_name_vaule”)
通过class_name定位元素: find_element_by_class_name(“class_name”)
通过css定位元素: find_element_by_css_selector()
通过xpath定位元素: find_element_by_xpath(“xpath”)
通过link: find_element_by_link_text(“text_vaule”)
通过 find_element_by_partial_link_text()
如果符合条件的节点有多个,则再使用find_element()系列的方法就只能得到匹配列表中第一个符合条件的节点了,要想拿到所有匹配成功的节点,则需要使用 find_elements() 系列的方法。
5.节点交互
Selenium 可以驱动浏览器来执行一些操作,也就是说可以让浏览器模拟执行一些动作。比较常见的用法有:输入文字时用send_keys()方法,清空文字时用clear()方法,点击按钮时用click()方法。
6.动作链(ActionChains)
action=ActionChains() 实例化一个动作链对象
action.click_and_hold(标签) 长按并且点击
action.release() 释放动作链
action.move_by_offset(x,y).perform()
perdorm()表示立即执行动作链操作;
x,y参数表示水平和竖直方向移动的像素大小
ActionChains(browser).move_to_element_with_offset(element,x,y)
切换参照物为element
7.模拟执行JavaScript
browser.execute_script(‘jscode’)
常见的jscode:
#模拟执行javascript将进度条拉到最底层
browser.execute_script('window.scrollTo(0, document.body.scrollHeight)')
#模拟页面下拉
browser.execute_script('window.scrollTo(0,document.body.scrollHeight)')
8.网页的前进和后退
browser.forward() 前进
browser.back() 后退
9.无可视化界面的操作(无头浏览器)
from selenium.webdriver.chrome.options import Options
path=r'驱动路径'
Chrome_options=Options()
Chrome_options.add_argument('--headless')
Chrome_options.add_argument('--disable-gpu')
browser=webdriver.Chrome(executable_path=path,chrome_options=Chrome_option)
browser.get('http://xxxx.com')
爬取动态加载的数据可以用无头浏览器,除了chrome还可以用phantomJS
10. 让selenium规避被检测到的风险
现在不少大网站有对selenium采取了监测机制,比如正常情况下我们用浏览器访问淘宝等网站的window.navigator.webdriver的值为undefined.而使用selenium访问则该值为true,那么如何解决这个问题呢?
只需要设置Chromedriver的启动参数即可解决问题,在启动Chromedriver之前,为Chrome开启实验性功能参数 excludeSwitches ,它的值为['enable-automation'] ,完整代码如下:
from selenium.webdriver import ChromeOptions
from selenium.webdriver import Chrome
option=ChromeOptions()
option.add_experimental_option('excludeSwitches',['enable-automation'])
driver=Chrome(options=option)
11.退出的一些操作
browser.close()
关闭当前窗口,如果它是当前打开的最后一个窗口,则退出浏览器
quit()
退出此驱动程序,关闭所有相关窗口
12.转到嵌套子页面中(iframe)
browser.switch_to.frame(‘iframeResult’)
通过iframe,可以使当前页面嵌套一个子页面,如果直接查找结点的方法是找不到iframe里面的内容的(查找的结果一般就是一个空列表),解决办法是通过switch_to.frame这个方法,让浏览器切换标签定位的作用域,再去查找结点
13.对图片的操作
browser.save_screenshot('photo.png')
将当前页面进行截图并且保存为photo.png;
这个操作可以用来模拟网页登陆时验证码的识别
裁剪图片
from selenium import webdriver
from PIL import Image
browser.save_screenshot('.//photo.png')
element=browseer.find_element_by_xpath('/html/body/script[1]')
#获取对应元素左上角的坐标
location=element.location
# #元素的长和宽
size=element.size
#左上角和右下角坐标
rangle=(int(location['x']),int(location['y']),
int(location['x']+size['width']),int(location['y'])+size['height'])
#裁剪图片
i=Image.open('.//photo.png')
img_name='.//01.png'
#crop根据指定区域进行裁剪
frame=i.crop(rangle)
frame.save(img_name)
14.获取cookie
browser.get_cookies()
15.获取网页源码
html = browser.page_source
16. 数据存储
存储到csv
import csv
with open('Jd_goods.csv','w',newline='') as f:
writer = csv.writer(f)
writer.writerow(['价格','商品名称','评价人数','店铺名'])
...
数据
...
writer.writerow([x,x,x,x,x])
17.隐式等待和显示等待
- 隐式等待
当使用隐式等待执行测试的时候,如果 Selenium 没有在 DOM 中找到节点,将继续等待,超出设定时间后,则抛出找不到节点的异常。
这里用 implicitly_wait
方法实现隐式等待。
示例如下:
```python
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
class JdSpider(object):
def __init__(self):
self.url = 'https://www.jd.com/'
self.browser = webdriver.Chrome()
隐式等待
self.browser.implicitly_wait(10)
def get_page(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(5)
next_button = self.browser.find_element_by_class_name('pn-next')
next_button.click()
def main(self):
self.get_page()
- 显示等待
指定要查找的节点,再指定一个最长等待时间。如果在指定时间内加载出来了这个节点,就返回查找的节点;如果到了指定时间没有加载出该节点,则抛出超时异常。
示例如下:
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
class JdSpider(object):
def __init__(self):
self.url = 'https://www.jd.com/'
self.browser = webdriver.Chrome()
#设置等待时间这里等待10秒,没0.5秒检查一次,第三个参数可省去
self.wait = WebDriverWait(self.browser,10,0.5)
def get_page(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()
# 显式等待
next_button=self.wait.until(EC.presence_of_element_located((By.CLASS_NAME,'pn-next')))
next_button.click()
def main(self):
self.get_page()
spider= JdSpider()
spider.main()