基于Python +Selenium的爬虫详解
转自:python专栏
一、selenium简介
二、selenium的安装与测试
3) 测试是否安装成功
import timefrom selenium import webdriverbrowser=webdriver.Chrome()#实例化1个谷歌浏览器对象browser.get('https://www.baidu.com/')time.sleep(5)browser.close()
👉点击领取:最全Python资料合集
三、selenium的使用
所谓模拟浏览器基本就是下面的流程:
1.请求 2.显示页面 3.查找元素 4.点击可点击元素
1) 通过标签id属性进行定位
browser.find_element_by_id('kw') # 其中kw便是页面中某个元素的id值
2) 通过标签name属性进行定位
# 两种方式是一样的browser.find_element_by_name("wd") # 其中wd是页面中某个元素的name值
3) 通过标签名进行定位
browser.find_element_by_tag_name("img") # img参数表示的就是图片标签img
4) 通过CSS查找方式进行定位
browser.find_elements_by_css_selector("#kw") # 根据选择器进行定位查找,其中#kw表示的是id选择器名称是kw的
5) 通过xpath方式定位
browser.find_element_by_xpath('//*[@id="kw"]') # 参数即是xpath的语法
有时候不是一个输入框也不是一个按钮,而是一个文字链接,我们可以通过link
browser.find_element_by_link_text("设置")
通过搜索页面中链接进行定位 ,可以支持模糊匹配**
browser.find_element_by_partial_link_text("百度") # 查找页面所有的含有百度的文字链接
2. selenium显示等待和隐式等待
显示等待:就是明确要等到某个元素的出现或者是某个元素的可点击等条件,等不到,就一直等,除非在规定的时间之内都没找到,就会跳出异常Exception
操作格式:WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)
from selenium import webdriverfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.common.by import Bydriver = webdriver.chrome()driver.get('http://www.baidu.com')element = WebDriverWait(driver, 5, 0.5).until(EC.presence_of_element_located((By.ID, "kw")))element.send_keys('selenium')
注意:在使用隐式等待的时候,实际上浏览器会在你自己设定的时间内部断的刷新页面去寻找我们需要的元素
driver.implicitly_wait() 默认设置为0
例如:driver.implicitly_wait(10) 。如果元素在10s内定位到了,继续执行。如果定位不到,将以循环方式判断元素是否被定位到。如果在10s内没有定位到,则抛出异常
from selenium import webdriverdriver = webdriver.chrome()driver.get('http://www.baidu.com')# 隐式等待10秒driver.implicitly_wait(10)
另外还有一种就是我们常用的sleep,我们称为:强制等待。有时候我们希望脚本在执行到某一位置时暂停一段时间等待页面加载,这时可以使用sleep()方法。sleep()方法会固定休眠一定的时长,然后再继续执行。sleep()方法默认参数以秒为单位。
from time import sleepfrom selenium import webdriverdriver = webdriver.chrome()driver.get('http://www.baidu.com')# 强制休眠2秒sleep(2)driver.find_element_by_id("kw").send_keys("selenium")
3. 元素交互操作
用selenium做自动化,有时候会遇到需要模拟鼠标操作才能进行的情况,比如单击、双击、点击鼠标右键、拖拽(滑动验证)等等。而selenium给我们提供了一个类来处理这类事件——ActionChains;
selenium.webdriver.common.action_chains.ActionChains(driver)
链式写法
menu = driver.find_element_by_css_selector(".div1")hidden_submenu = driver.find_element_by_css_selector(".div1 #menu1")ActionChains(driver).move_to_element(menu).click(hidden_submenu).perform()
分步写法
menu = driver.find_element_by_css_selector(".div1")hidden_submenu = driver.find_element_by_css_selector(".div1 #menu1")actions = ActionChains(driver)actions.move_to_element(menu)actions.click(hidden_submenu)actions.perform()
2) actionChains方法列表:
click(on_element=None) ——单击鼠标左键click_and_hold(on_element=None) ——点击鼠标左键,不松开context_click(on_element=None) ——点击鼠标右键double_click(on_element=None) ——双击鼠标左键drag_and_drop(source, target) ——拖拽到某个元素然后松开drag_and_drop_by_offset(source, xoffset, yoffset) ——拖拽到某个坐标然后松开key_down(value, element=None) ——按下某个键盘上的键key_up(value, element=None) ——松开某个键move_by_offset(xoffset, yoffset) ——鼠标从当前位置移动到某个坐标move_to_element(to_element) ——鼠标移动到某个元素move_to_element_with_offset(to_element, xoffset, yoffset) ——移动到距某个元素(左上角坐标)多少距离的位置perform() ——执行链中的所有动作release(on_element=None) ——在某个元素位置松开鼠标左键send_keys(*keys_to_send) ——发送某个键到当前焦点的元素send_keys_to_element(element, *keys_to_send) ——发送某个键到指定元素
from selenium import webdriverfrom selenium.webdriver.common.keys import Keysimport timetry:driver = webdriver.Chrome()driver.implicitly_wait(10)# 1、往jd发送请求driver.get('https://www.jd.com/')# 找到输入框输入围城input_tag = driver.find_element_by_id('key')input_tag.send_keys('华为')# 键盘回车input_tag.send_keys(Keys.ENTER)time.sleep(2)# 找到输入框输入墨菲定input_tag = driver.find_element_by_id('key')input_tag.clear()input_tag.send_keys('樊登读书')# 找到搜索按钮点击搜索button = driver.find_element_by_class_name('button')button.click()time.sleep(10)finally:driver.close()
或者前进后退相关
import timefrom selenium import webdriverbrowser = webdriver.Chrome()browser.get('https://www.cnblogs.com/xuanyuan/')browser.find_element_by_partial_link_text('我是如何把计算机网络考了100分的?').click()time.sleep(3)browser.back() # 后退time.sleep(3)browser.forward() # 前进time.sleep(5)browser.close()
四、综合案例
import osfrom selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support import expected_conditions as EC # available since 2.26.0from selenium.webdriver.support.ui import WebDriverWait # available since 2.4.0from selenium.webdriver.support import expected_conditionsimport pandas as pdclass MyCrawler(object):def __init__(self):self.path = "./data"if not os.path.exists(self.path):os.mkdir(self.path)self.driver = webdriver.Chrome()self.base_url = "http://data.house.163.com/bj/housing/trend/district/todayprice/{date:s}/{interval:s}/allDistrict/1.html?districtname={disname:s}#stoppoint"self.data = Nonedef craw_page(self, date="2020.01.01-2020.12.30", interval="month", disname="全市"):driver = self.driverurl = self.base_url.format(date=date, interval=interval, disname=disname)driver.get(url)try:WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "resultdiv_1")))self.data = pd.DataFrame()ct = Truewhile ct:self.get_items_in_page(driver)e_pages = driver.find_elements_by_xpath('//div[@class="pager_box"]/a[@class="pager_b current"]/following::a[@class="pager_b "]')if len(e_pages) > 0:next_page_num = e_pages[0].texte_pages[0].click()# 通过判断当前页是否为我们点击页面的方式来等待页面加载完成WebDriverWait(driver, 10).until(expected_conditions.text_to_be_present_in_element((By.XPATH, '//a[@class="pager_b current"]'),next_page_num))else:ct = Falsebreareturn self.datafinally:driver.quit()def get_items_in_page(self, driver):e_tr = driver.find_elements_by_xpath("//tr[normalize-space(@class)='mBg1' or normalize-space(@class)='mBg2']")temp = pd.DataFrame(e_tr, columns=['web'])temp['时间'] = temp.web.apply(lambda x: x.find_element_by_class_name('wd2').text.split(' ')[0])temp['套数'] = temp.web.apply(lambda x: x.find_element_by_class_name('wd5').text)temp['均价'] = temp.web.apply(lambda x: x.find_element_by_class_name('wd7').text)temp['去化'] = temp.web.apply(lambda x: x.find_element_by_class_name('wd14').text)del temp['web']self.data = pd.concat([temp, self.data], axis=0)mcraw = MyCrawler()data = mcraw.craw_page()data= data.sort_values(by='时间')print(data.to_string(index=False))
热门推荐