selenium+phantomjs/Chrome/Firefox
1.定义
1、Web自动化测试工具,可运行在浏览器,根据指令操作浏览器
2、只是工具,必须与第三方浏览器结合使用
2.安装
Linux: sudo pip3 install selenium
Windows: python -m pip install selenium
二
1、下载对应版本的phantomjs、chromedriver、geckodriver 2、把chromedriver.exe拷贝到python安装目录的Scripts目录下(添加到系统环境变量) # 查看python安装路径: where python 3、验证 cmd命令行: chromedriver # 下载地址 1、chromedriver : 下载对应版本 http://chromedriver.storage.googleapis.com/index.html 2、geckodriver https://github.com/mozilla/geckodriver/releases 3、phantomjs https://phantomjs.org/download.html
Linux
1、下载后解压 tar -zxvf geckodriver.tar.gz 2、拷贝解压后文件到 /usr/bin/ (添加环境变量) sudo cp geckodriver /usr/bin/ 3、更改权限 sudo -i cd /usr/bin/ chmod 777 geckodriver
3.使用
示例代码一:使用 selenium+浏览器 打开百度
from selenium import webdriver import time 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/') # 向搜索框(id kw)输入 赵丽颖 ele = browser.find_element_by_xpath('//*[@id="kw"]') ele.send_keys('赵丽颖') time.sleep(1) # 点击 百度一下 按钮(id su) su = browser.find_element_by_xpath('//*[@id="su"]') su.click() # 截图 browser.save_screenshot('赵丽颖.png') # 关闭浏览器 browser.quit()
浏览器对象(browser)方法
1、browser = webdriver.Chrome(executable_path='path') 2、browser.get(url) 3、browser.page_source # 查看响应内容 4、browser.page_source.find('字符串') # 从html源码中搜索指定字符串,没有找到返回:-1 5、browser.quit() # 关闭浏览器
定位节点
单元素查找(一个节点对象)
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('')
多元素查找([节点对象列表])
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('')
节点对象操作
1、ele.send_keys('') # 搜索框发送内容 2、ele.click() 3、ele.text # 获取文本内容,包含自己诶单和后代节点的文本内容 4、ele.get_attribute('src') # 获取属性值
京东爬虫案例
目标
1、目标网址 :https://www.jd.com/ 2、抓取目标 :商品名称、商品价格、评价数量、商品商家
思路提醒
1、打开京东,到商品搜索页 2、匹配所有商品节点对象列表 3、把节点对象的文本内容取出来,查看规律,是否有更好的处理办法? 4、提取完1页后,判断如果不是最后1页,则点击下一页 # 如何判断是否为最后1页???
实现步骤
1.找节点
1、首页搜索框 : //*[@id="key"] 2、首页搜索按钮 ://*[@id="search"]/div/div[2]/button 3、商品页的 商品信息节点对象列表 ://*[@id="J_goodsList"]/ul/li
2.执行JS脚本,获取动态加载数据
browser.execute_script( 'window.scrollTo(0,document.body.scrollHeight)' )
3.代码实现
from selenium import webdriver import time class JdSpider(object): def __init__(self): self.browser = webdriver.Chrome() self.url = 'https://www.jd.com/' self.i = 0 # 获取商品页面 def get_page(self): self.browser.get(self.url) # 找2个节点 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(2) # 解析页面 def parse_page(self): # 把下拉菜单拉到底部,执行JS脚本 self.browser.execute_script( 'window.scrollTo(0,document.body.scrollHeight)' ) time.sleep(2) # 匹配所有商品节点对象列表 li_list = self.browser.find_elements_by_xpath('//*[@id="J_goodsList"]/ul/li') for li in li_list: li_info = li.text.split('\n') if li_info[0][0:2] == '每满': price = li_info[1] name =li_info[2] commit = li_info[3] market = li_info[4] else: price = li_info[0] name = li_info[1] commit = li_info[2] market = li_info[3] print('\033[31m************************************\033[0m') print(price) print(commit) print(market) print(name) self.i += 1 # 主函数 def main(self): self.get_page() while True: self.parse_page() # 判断是否该点击下一页,没有找到说明不是最后一页 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()
import requests from selenium import webdriver import time class JdSpider(): 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) # 获取页面信息 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(2.3) # 添加计数 self.i = 0 # 解析页面 def parse_html(self): #把进度条拉倒底部,是所有数据动态加载 self.browser.execute_script( 'window.scrollTo(0,document.body.scrollHeight)' ) #等待动态数据加载完成 time.sleep(2) item = {} # 先提取所有商品节点对象列表,li列表 li_list = self.browser.find_elements_by_xpath('//*[@id="J_goodsList"]/ul/li') 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(2) else: break print('数量', self.i) self.browser.quit() if __name__ == '__main__': jd = JdSpider() jd.main()