selenium-replace

页面等待

现在的网页越来越多采用了 Ajax 技术,这样程序便不能确定何时某个元素完全加载出来了。如果实际页面等待时间过长导致某个dom元素还没出来,但是你的代码直接使用了这个WebElement,那么就会抛出NullPointer的异常。为了解决这个问题。所以 Selenium 提供了两种等待方式:一种是隐式等待、一种是显式等待

  • 隐式等待:调用driver.implicitly_wait。那么在获取不可用的元素之前,会先等待10秒中的时间
    driver.implicitly_wait(10)

  • 显示等待:显示等待是表明某个条件成立后才执行获取元素的操作。也可以在等待的时候指定一个最大的时间,如果超过这个时间那么就抛出一个异常。显示等待应该使用selenium.webdriver.support.excepted_conditions期望的条件和selenium.webdriver.support.ui.WebDriverWait来配合完成

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
driver = webdriver.Chrome()
driver.get("https://www.baidu.com/")
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "myDynamicElement"))
)

一些其他的等待条件

  • presence_of_element_located:某个元素已经加载完毕了。
  • presence_of_all_elements_located:网页中所有满足条件的元素都加载完毕了。
  • element_to_be_clickable:某个元素是可以点击了。

更多条件请参考:http://selenium-python.readthedocs.io/waits.html

打开多窗口和切换页面

  • 有时候窗口中有很多子tab页面。这时候肯定是需要进行切换的。selenium提供了一个叫做switch_to_window来进行切换,具体切换到哪个页面,可以从driver.window_handles中找到
  • 打开一个新的页面
    driver.execute_script("window.open('url')")
    print(driver.current_url)
  • 切换到这个新的页面中
    driver.switch_to_window(self.driver.window_handles[1])
  • 同时打开两个URL,其中"https://www.douban.com/"仅是打开,可编辑的网址是https://www.baidu.com/
from selenium import webdriver
driver = webdriver.Chrome()
driver.get('https://www.baidu.com/')
driver.execute_script('window.open("https://www.douban.com/")')
print(driver.current_url)
运行结果:
https://www.baidu.com/
  • 同时打开两个URL,使"https://www.douban.com/"变为可编辑的网址,https://www.baidu.com/仅是打开。driver.switch_to.window(driver.window_handles[1])
from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.get('https://www.baidu.com/')
driver.execute_script('window.open("https://www.douban.com/")')
print(driver.current_url)
driver.switch_to.window(driver.window_handles[1])
time.sleep(1)
print(driver.current_url)
运行结果
https://www.baidu.com/
https://www.douban.com/

execute_script()记忆点

  • 滚动到当前页面的最下端,目的是通过滚动让ajax把页面数据都加载出来。
    driver.execute_script(
    'window.scrollTo(0,document.body.scrollHeight)'
    )
  • 在当前网页打开新的网页
    driver.execute_script('window.open("https://www.douban.com/")')
  • input标签type="hidden"时,必须通过execute_script()解决
    driver.execute_script('arguments[0].value="%s"'%from_station_code(把这个标签源标签),from_station_input(替换成这个标签目标标签)
  • 按钮不能够被点击btn代表按扭定位元素变量
    driver.execute_script('arguments[0].click()',btn)

设置无界面

options = webdriver.ChromeOptions()
options.add_argument('--headless')
driver = webdriver.Chrome(options=options)

import csv
from selenium import webdriver

class MaoyanSprider(object):

    def __init__(self):
        self.options = webdriver.ChromeOptions()
        self.options.add_argument('--headless')
        self.driver = webdriver.Chrome(options = self.options)
        self.driver.get('https://maoyan.com/board/4')
        self.driver.maximize_window()

    def Maoyanparse(self):

        items = self.driver.find_elements_by_xpath('//*[@id="app"]/div/div/div[1]/dl/dd')
        mao_list=[]
        for item in items:
            maoyanitem = item.text
            maoitem = maoyanitem.split('\n')
            # print(maoitem)
            maoyandict = {}
            try:
                maoyandict['rank'] = maoitem[0]
                maoyandict['name'] = maoitem[1]
                maoyandict['actor'] = maoitem[2]
                maoyandict['time'] = maoitem[3]
                maoyandict['score'] = maoitem[4]
                mao_list.append(maoyandict)
            except:
                pass
        return mao_list

    def WriteDate(self,mao_list):
        hr = ['rank','name','actor','time','score']
        with open('maoyan.csv','w',encoding='utf-8') as f:
            writer = csv.DictWriter(f,hr)
            writer.writeheader()
            writer.writerows(mao_list)

    def main(self):
        mao_list=[]
        while True:
            mao_list += self.Maoyanparse()
            self.WriteDate(mao_list)
            try:
                self.driver.find_element_by_link_text('下一页').click()
            except:
                self.driver.quit()
                break


if __name__ == '__main__':
    mao = MaoyanSprider()
    mao.main()

案例-动态网页

第一步 页面分析 我们发现 所有的商品信息数据都是在一个ul标签 ul标签下面每一个li标签对应的就是一个商品完整信息。
我们拖动 拖动条(滚轮)的时候 页面又加载了数据,当我们进入这个页面的时候,把这个拖动条拖动一下,拖到最下面,然后等它加载一会儿,等页面元素加载完了之后,我们再去抓取,每页 上来先加载30个 当我们进行拖动的时候 它又会加载30个 也就是每页其实是60个数据。
第二步 如何拖动 拖动条? 我们会用到一个 加载js的方法driver.execute_script(
'window.scrollTo(0,document.body.scrollHeight)'
)
第三步数据解析:
items = self.driver.find_elements_by_xpath('//*[@id="J_goodsList"]/ul/li')
items_list=[]
for item in items:
price = item.find_element_by_xpath('.//div[@class="p-price"]/strong/i').text.strip()
title = item.find_element_by_css_selector('.p-name.p-name-type-2>a>em').text.strip().replace('京品手机','').replace('拍拍','').strip()
shop = item.find_element_by_xpath('.//div[@class="p-shop"]/span/a').text.strip()
commit = item.find_element_by_xpath('.//div[@class="p-commit"]/strong/a').text.strip()
jd_list =[price,title,shop,commit]
items_list.append(jd_list)
第四步 翻页处理
找规律 我们先看最后一页 发现这个 下一页的按钮还在
if self.driver.page_source.find("pn-next disabled")== -1:
self.driver.find_element_by_class_name("pn-next").click()
time.sleep(2)
else:
self.driver.quit()
break

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
import time
import csv

class JdSprider(object):

    def __init__(self):
        self.driver = webdriver.Chrome()
        self.url = 'https://www.jd.com/'
        self.driver.get(self.url)
        self.driver.maximize_window()
        self.element = WebDriverWait(self.driver, 1000).until(
            EC.presence_of_element_located((By.ID, "key"))
        )
        self.element.send_keys('苹果手机')
        self.botton =  WebDriverWait(self.driver, 1000).until(
            EC.presence_of_element_located((By.CLASS_NAME, "button"))
        ).click()

    def jdparse(self):
        self.driver.execute_script(
            'window.scrollTo(0,document.body.scrollHeight)'
        )
        time.sleep(3)
        items = self.driver.find_elements_by_xpath('//*[@id="J_goodsList"]/ul/li')
        items_list=[]
        for item in items:
            price = item.find_element_by_xpath('.//div[@class="p-price"]/strong/i').text.strip()
            title = item.find_element_by_css_selector('.p-name.p-name-type-2>a>em').text.strip().replace('京品手机','').replace('拍拍','').strip()
            shop = item.find_element_by_xpath('.//div[@class="p-shop"]/span/a').text.strip()
            commit = item.find_element_by_xpath('.//div[@class="p-commit"]/strong/a').text.strip()
            jd_list =[price,title,shop,commit]
            items_list.append(jd_list)
        return items_list

    def WriteDate(self,item_list):
        hr =['price','title','shop','commit']
        with open('jdsearch.csv','w',encoding='utf-8') as f:
            writer = csv.writer(f)
            writer.writerow(hr)
            writer.writerows(item_list)

    def main(self):
        items_list =[]
        while True:
            items_list += self.jdparse()
            self.WriteDate(items_list)
            if self.driver.page_source.find("pn-next disabled")== -1:
                self.driver.find_element_by_class_name("pn-next").click()
                time.sleep(2)
            else:
                self.driver.quit()
                break

if __name__ == '__main__':

    jd = JdSprider()
    jd.main()

你可能感兴趣的:(selenium-replace)