Python使用Selenium Webdriver爬取网页所有内容
- 一、为什么我抓不到网页的全部html内容
- 二、Selenium的基本使用
- 三、使用Selenium抓取全部HTML
一、为什么我抓不到网页的全部html内容
有时候,我们在用urllib或者requests库抓取页面时,得到的html源代码和浏览器中看到的不一样。这将是我们面临的一个非常常见的问题。现在网页越来越多地采用Ajax、前端模块化工具来构建,整个网页可能都是由JavaScript渲染出来的,也就是说原始的HTML代码可能就是一个空壳,例如:
<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title>this is a demo</title></head><body><div id="container"></div></body><script src="app.js"></script></html>
body节点里面只有一个id为container的节点,但是需要注意在body节点后引入了app.js, 它便负责整个网站的渲染。
在浏览器中打开这个页面时,首先会加载这个HTML内容,接着浏览器会发现其中引入了一个app.js文件,然后便会接着去请求这个文件,获取到该文件后,便会执行其中的JavaScript代码,而JavaScript则会改变HTML中的节点,向其中添加内容,最后得到完整的页面。
但是在用urllib或者requests等库请求当前页面时,我们得到的只是这个HTML代码,它不会帮助我们去继续加载这个JavaScript文件,这样也就看不到浏览器中的内容了。
而且,JavaScript动态渲染的页面可不止Ajax这一种,还有其他各种原因会导致我们得到的源代码和浏览器中看到的不一样。
对于抓不到全部html内容的情况,我们能采取什么应对措施呢,本文介绍一种可行的方法,就是通过Selenium webdriver来模拟浏览器运行的方式,这样就可以做到在浏览器中看到是什么样,抓取的源码就是什么样,也就是可见即可爬。这样,我们就不用再去管网页内部的JavaScript用了什么算法渲染页面,也不用管网页后台的Ajax接口到底有哪些参数。所有的这些,都交给Selenium webdriver来帮我们完成。
二、Selenium的基本使用
Selenium是一个自动化测试工具,利用它可以驱动浏览器执行特定的动作,如点击、下拉等操作,同时还可以获取浏览器当前呈现的页面的源代码,做到可见即可爬。对于一些JavaScript动态渲染的页面来说,此种抓取方式非常有效。
Selenium webdriver的安装和基本使用方法,可以参考另一篇文章。
Python使用Selenium WebDriver的入门介绍及安装教程
Selenium的官方网站:
Selenium WebDriver
一些基本的用法,此处不再赘述。
三、使用Selenium抓取全部HTML
先看使用requests库直接提取到的代码,可以发现并不是完整的:
使用Selenium拿到的html代码,可以看到已经可以通过src属性提取到图片的url:
示例代码如下,详细的解读可以参考每一步的注释:
from selenium.webdriver import Firefox, FirefoxOptions
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import Byclass ContentPageParser():def __init__(self, content_page_url) -> None:self.content_url = content_page_url # 抓取content_page_url页面上全部的图片urlself.img_src = [] # 保存当前页面上所有的图片urldef visit_content_page_with_firefox(self):option = FirefoxOptions()# 设置浏览器为无头模式,使用过程中不会弹出浏览器页面option.headless = Trueself.driver = Firefox(options=option)try:# 打开待抓取的url页面self.driver.get(self.content_url)# 设置灵活等待,最长等待10s,轮询间隔为1swait = WebDriverWait(self.driver, timeout=10, poll_frequency=1)# 使用css选择器进行元素定位,直到元素可见为止wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, 'img[class="showimg"]')))# 使用css选择器查找所有元素imgs = self.driver.find_elements(By.CSS_SELECTOR, 'img[class="showimg"]')# 提取所有图片的urlfor img in imgs:self.img_src.append(img.get_attribute('src'))except Exception as e:print(repr(e))finally:# 关闭webdriverself.driver.close() def get_img_src(self):return self.img_srcif __name__ == '__main__':content_parser = ContentPageParser('https://xxx/content_48495.html')content_parser.visit_content_page_with_firefox()img = content_parser.get_img_src()print(img)