Python3+Selenium爬取动态网页数据

版权声明:未经博主同意不得转载 https://blog.csdn.net/bluefish89/article/details/84317623

背景:

有时候想获取网页的信息,然后下载里面的图片资料等等

遇到的问题:

有时一些网页是动态的,一些内容是通过js异步拉取,甚至拉取时间是懒加载的,例如滚动到元素位置的时候才加载

解决方案:

这个时候就需要Selenium神器了

Selenium 是什么?一句话,自动化测试工具。它支持各种浏览器,包括 Chrome,Safari,Firefox 等主流界面式浏览器,如果你在这些浏览器里面安装一个 Selenium 的插件,那么便可以方便地实现Web界面的测试。换句话说叫 Selenium 支持这些浏览器驱动。

PS:PhantomJS不也是一个浏览器吗, Selenium 支持是肯定的,这样二者便可以实现无缝对接了实现 ,PhantomJS是一个无界面的浏览器对象,为什么不直接用浏览器而用一个没界面的 PhantomJS 呢?答案是:效率高啊! 这样构成了一完美的爬取流程:
Python+PhantomJS+Selenium 爬虫三剑客
PhantomJS 用来渲染解析JS
Selenium 用来驱动以及与 Python 的对接,
Python 进行后期的处理

我们这里单Selenium拎出来讲,
简介:http://www.51testing.com/zhuanti/webdriver.htm
官网:https://www.seleniumhq.org/docs/index.jsp
文档:https://selenium-python.readthedocs.io/index.html

实践:

安装

pip3 install selenium

你也可以下载源码安装,下载后执行

python3 setup.py install

使用:

from selenium import webdriver
 
browser = webdriver.Chrome()
browser.get('http://www.baidu.com/')
html = driver.page_source

运行后会启动浏览器
需要安装浏览器驱动
https://sites.google.com/a/chromium.org/chromedriver/downloads
下载后把chromedriver放到/usr/local/bin

sudo mv /Users//Downloads/chromedriver /usr/local/bin

driver.get 方法会打开请求的URL,WebDriver 会等待页面完全加载完成之后才会返回,
即程序会等待页面的所有内容加载完成,JS渲染完毕之后才继续往下执行。注意:如果这里用到了特别多的 Ajax 的话,程序可能不知道是否已经完全加载完毕。
page_source获取网页源码

懒加载动态页面
有一些网页,元素可能是需要滚动到特定位置才加载的,这种就需要设置一个等待时间来等待页面元素出现才返回
这里可以使用显示等待WebDriverWait

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

#显式等待,直到offer-template-0出现
driver = webdriver.Chrome()
driver.get(url)

#滚动到某元素
target = driver.find_element_by_id('desc-lazyload-container')
driver.execute_script("arguments[0].scrollIntoView();", target)

try:
    WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.ID, "offer-template-0"))
    )
except:
    driver.quit()    
    
html = driver.page_source

其中,presence_of_element_located是一个等待条件
下面是一些内置的等待条件,你可以直接调用这些条件,而不用自己写某些等待条件了。

title_is
title_contains
presence_of_element_located
visibility_of_element_located
visibility_of
presence_of_all_elements_located
text_to_be_present_in_element
text_to_be_present_in_element_value
frame_to_be_available_and_switch_to_it
invisibility_of_element_located
element_to_be_clickable – it is Displayed and Enabled.
staleness_of
element_to_be_selected
element_located_to_be_selected
element_selection_state_to_be
element_located_selection_state_to_be
alert_is_present

页面操作
这里使用到find_element_by_id的页面操作来获取元素,例如:

element = driver.find_element_by_id("passwd-id")
element = driver.find_element_by_name("passwd")
element = driver.find_elements_by_tag_name("input")
element = driver.find_element_by_xpath("//input[@id='passwd-id']")

然后通过

driver.execute_script("arguments[0].scrollIntoView();", target)

注入js,滚动到元素位置(懒加载)

我们还可以对元素执行其他模拟操作
获取了元素之后,下一步当然就是向文本输入内容了,可以利用下面的方法

element.send_keys("some text")

同样你还可以利用 Keys 这个类来模拟点击某个按键。

element.send_keys("and some", Keys.ARROW_DOWN)

你可以对任何获取到到元素使用 send_keys 方法,就像你在 GMail 里面点击发送键一样。不过这样会导致的结果就是输入的文本不会自动清除。所以输入的文本都会在原来的基础上继续输入。你可以用下面的方法来清除输入文本的内容。

element.clear()

这样输入的文本会被清除。

最后,爬取到最终完整的html后,就可以靠BeautifulSoup等工具继续解析了

猜你喜欢

转载自blog.csdn.net/bluefish89/article/details/84317623
今日推荐