赞
踩
前面总结了通过寻找后台接口来爬取动态网页,这篇博客总结一下selenium+chrome如何爬取动态页面,selenium现在貌似不在支持PhantomJs,python版本为3.6
Xpath的/与//的不同:/是在它的子结点中查找,而//是在它的所有子结点中查找,包括子结点的子结点等等
网址:http://chromedriver.chromium.org/downloads(需要翻墙)
请安装与自己chrome版本(在浏览器地址栏输入chrome://settings/help可查看)一致的chromedriver
下载完后,将chromedriver的所有文件拖到chrome的安装文件夹,设置到chrome安装文件夹的环境变量(方便代码处理)
网址:http://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.chrome.webdriver
常用函数总结一下:
- #selenium.webdriver.chrome.webdriver.WebDriver类
- __init__:第一个形参用于指定chromedriver的路径,如果不指定,使用
- 环境变量path下的路径,第二个参数指定运行端口号,如果不指定,随便选择一个空端口号
- quite():关闭浏览器
- #selenium.webdriver.chrome.options.Options
- 用于设置chrome浏览器,目前使用过的参数:
- 1、阻止chrome弹窗的出现:'profile.default_content_setting_values' :{'notifications' : 2}
- 2、不加载图片:"profile.managed_default_content_settings.images":2
- 3、无头浏览器,--headless
-
- add_experimental_option(name, value):将设置参数传递给chrome
- #selenium.webdriver.remote.webdriver.WebDriver
- close():关闭当前窗口
- execute_async_script():异步执行js代码
- execute_script():同步执行js代码
- quit():关闭驱动以及所有窗口
- get(url):获得某个页面
- set_window_size(width, height, windowHandle='current'):设置窗口大小
- maximize_window():窗口最大化
- page_source属性,获得当前页面的html代码
- driver.execute_script("window.scrollTo(0, document.body.scrollHeight);":执行翻页
- find_element_by_id:全文查找,根据完整的id值查找,返回selenium.webdriver.remote.webelement.WebElement对象
- find_element_by_class_name:全文查找,根据完整的class值查找,返回selenium.webdriver.remote.webelement.WebElement对象
- find_element_by_xpath(xpath):全文查找,根据xpath查找,返回selenium.webdriver.remote.webelement.WebElement对象
- #selenium.webdriver.remote.webelement.WebElement
- click():点击按钮
- find_element_by_id:根据id查找,返回selenium.webdriver.remote.webelement.WebElement对象,只查找子元素
- find_element_by_class_name:根据class name查找,返回selenium.webdriver.remote.webelement.WebElement对象,只查找子元素
- find_element_by_xpath(xpath):根据xpath查找,返回selenium.webdriver.remote.webelement.WebElement对象,只查找子元素
- submit():提交表单
- send_keys():填值
- text属性:该元素的文本值
NoSuchElementException
关于起因,我总结了两点:
1、页面元素未被加载出来,这里有两种可能
第一、等待时间过短,导致元素未加载
第二、浏览器窗口不够大,导致页面元素未加载,此时不论等待多长时间都没用,因此,每次都要将窗口设置为最大值
2、寻找元素的标记本身发生错误
爬取迪丽热巴的微博发言,由于是练习,因此会有一些不必要的步骤
引入的包:
- from selenium import webdriver
- import time
- from lxml import etree
- options = webdriver.ChromeOptions()
- prefs = {
- 'profile.default_content_setting_values' :
- {
- 'notifications' : 2
- },
- "profile.managed_default_content_settings.images":2
- }
- options.add_experimental_option('prefs',prefs)
- driver = webdriver.Chrome(chrome_options = options)
- driver.maximize_window()
禁止chrome弹窗(注意是chrome自带的弹窗,不是网站的弹窗)、不加载图片
注意到弹窗的存在,如果不设置,chrome就会有弹窗,但是不妨碍处理网页
登陆用户具有更多的浏览权限,因此需要登陆
- def login_weibo():
- driver.get('https://weibo.com/')
- time.sleep(10)
-
- element=driver.find_element_by_id('loginname')
- element.send_keys('你的账号名')
-
- element=driver.find_element_by_name('password')
- element.send_keys('你的密码')
- element=driver.find_element_by_class_name('W_btn_a')
- element.click()
这里有一个坑,如果不最大化窗口,微博首页的登陆框是不会出现的(google、百度了一堆,没啥用,然后才发现这么回事.....
这个登陆方式不是很完善,没有验证码的处理,但验证码并不常见(尝试登陆了几十次,没见过验证码.......),所以就不写了,出现验证码可以尝试用OCR的识别手段,也可以考虑自己手工输入
- def search_weibo():
- #查找搜索框并输入信息
- elements=driver.find_elements_by_class_name('W_input')
- elements[0].send_keys('迪丽热巴')
- #点击搜索按钮
- element=driver.find_element_by_class_name('ficon_search')
- element.click()
- time.sleep(10)
- #进入迪丽热巴的微博
- element=driver.find_element_by_class_name('name_txt')
- element.click()
- time.sleep(10)
这里设置了等待时间,因为整个页面的加载速度奇慢,如果等待时间不足,可能相应的元素就无法加载
这个权限在登陆后才有
- def select_all():
- #定位最新打开的窗口
- windows = driver.window_handles
- driver.switch_to.window(windows[-1])
- #选择全部按钮,点击
- element=driver.find_element_by_xpath("//li[@class='tab_li tab_li_first']/a")
- element.click()
- time.sleep(10)
这里有个坑,如果我们用selenium让chrome打开了多个窗口,chrome的webdriver不会定位到最新的窗口,而是一直处于第一个窗口,所以前两行代码用于定位最新打开的窗口
- def crawel():
- i=0
- while(i!=3):
- #翻页
- driver.execute_script("window.scrollTo(0, document.body.scrollHeight)")
- time.sleep(5)
- #使用etree查看是否有下一页元素
- page=driver.page_source
- html_parse=etree.HTML(page)
- a=html_parse.xpath("//a[@class='page next S_txt1 S_line1']")
- #存在下一页元素,此时该页全部加载完毕,爬取
- if a!=[]:
- text_list=html_parse.xpath("//div[@class='WB_text W_f14']")
- for index in range(0,len(text_list)):
- result=text_list[index].text.replace(' ','').replace('\n','')
- if result!='':
- file.write(result+'\n')
- element=driver.find_element_by_class_name('next')
- element.click()
- i=i+1
微博需要下拉一定长度才会出现下一页的标签,在网上查找了许多下拉网页的方式都没用,最后查阅官方文档才找到答案:
driver.execute_script("window.scrollTo(0, document.body.scrollHeight)")
lxml元素选择器的处理速度比selenium快很多,查找不到也不会抛异常,因此,寻找下一页元素我选择使用lxml(网页要下拉到最底才会出现下一页标识符,未出现下一页标识符,selenium会抛异常),这里没有处理因网络原因导致的重新加载情况
- 果然,最喜欢夏天
- 自从这个妹妹出道以后老学我
- 希望平安无事
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。