python爬虫笔记(五)——动态网页处理(下篇)

前面总结了通过寻找后台接口来爬取动态网页,这篇博客总结一下selenium+chrome如何爬取动态页面,selenium现在貌似不在支持PhantomJs,python版本为3.6

1、安装chromedriver

网址:http://chromedriver.chromium.org/downloads(需要翻墙)

请安装与自己chrome版本(在浏览器地址栏输入chrome://settings/help可查看)一致的chromedriver

下载完后,将chromedriver的所有文件拖到chrome的安装文件夹,设置到chrome安装文件夹的环境变量(方便代码处理)

2、查看selenium官方文档

网址: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属性:该元素的文本值

3、常见异常

NoSuchElementException

关于起因,我总结了两点:

1、页面元素未被加载出来,这里有两种可能

第一、等待时间过短,导致元素未加载

第二、浏览器窗口不够大,导致页面元素未加载,此时不论等待多长时间都没用,因此,每次都要将窗口设置为最大值

2、寻找元素的标记本身发生错误

4、实例

爬取迪丽热巴的微博发言,由于是练习,因此会有一些不必要的步骤

引入的包:

from selenium import webdriver
import time
from lxml import etree

1、实例化webdriver

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自带的弹窗,不是网站的弹窗)、不加载图片

2、登陆微博

注意到弹窗的存在,如果不设置,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的识别手段,也可以考虑自己手工输入

3、在搜索框搜索迪丽热巴并点击

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)

这里设置了等待时间,因为整个页面的加载速度奇慢,如果等待时间不足,可能相应的元素就无法加载

4、选在查看全部微博

这个权限在登陆后才有

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不会定位到最新的窗口,而是一直处于第一个窗口,所以前两行代码用于定位最新打开的窗口

5、爬取前三页微博信息

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会抛异常),这里没有处理因网络原因导致的重新加载情况

6、部分执行结果(CSDN不知咋回事,只能丢出这么点文本)

果然,最喜欢夏天
自从这个妹妹出道以后老学我
希望平安无事

猜你喜欢

转载自blog.csdn.net/dhaiuda/article/details/81406853