遇到动态渲染的问题时,如果无法提取
ajax
接口,或者无法破解token
值计算,那我们只能使用终极绝招,Selenium
测试框架。只是它性能低,不适合服务器部署,但活人不能让尿憋死,这是无奈的选择。
这里简单解释一下什么是Selenium,它其实是一个网站前端压力测试框架,更通俗的说,它能直接操作浏览器,试想一下,网页是在浏览器里面加载的,如果我们能用代码操控浏览器,那我们想要爬取什么数据不能通过浏览器获取?无所不爬!
环境准备
安装 selenium
代码语言:javascript复制1 python -m pip install selenium
安装浏览器驱动 想要操作浏览器,当然需要浏览器驱动了,这些驱动是浏览器官方提供的,如果你用的小众浏览器,那建议你赶紧装一个谷歌浏览器Chrome,它是目前最流畅最好用的。
Selenium支持的其他浏览器都有其对应的驱动器
下载驱动后,将解压得到的可执行程序路径添加到本地PATH
环境变量中,或者将可执行程序拷贝到python根目录下。
代码示例
以下设置了无头浏览器,即无界面后台运行,可以节省GPU开销,但我个人经验,使用无头模式,爬取的速度反而更慢,大家可以把设置无头模式的那两行代码注释后自测一下速度,请谨慎选择。
代码语言:javascript复制 1 from selenium.webdriver.chrome.options import Options
2 from selenium import webdriver
3 from selenium.webdriver.common.by import By
4
5 chrome_options = Options()
6 # 设置无头浏览器
7 chrome_options.add_argument('--headless')
8 chrome_options.add_argument('--disable-gpu')
9 # 设置代理
10 chrome_options.add_argument("--proxy-server=http://127.0.0.1:1080")
11
12 # 创建浏览器实例
13 browser = webdriver.Chrome(chrome_options=chrome_options)
14 # 打开网页
15 browser.get("http://www.solidfiles.com/v/nYdm5gVQ2DRyY")
16 # 查找元素
17 browser.find_elements(By.XPATH, '//*/form/button')[0].submit()
示例2
注意,这里还能通过browser.page_source
获取经过selenium动态渲染之后的网页,然后再使用我们之前介绍过的bs4
来解析元素
1 import cookie_handle as ch
2 from selenium.webdriver.chrome.options import Options
3 from selenium import webdriver
4 from bs4 import BeautifulSoup
5
6 # 处理自动登录时,可将已登录的Cookies值复制到此处
7 cookies = ""
8
9 chrome_options = Options()
10 # 设置无头浏览器
11 # chrome_options.add_argument('--headless')
12 # chrome_options.add_argument('--disable-gpu')
13
14 browser = webdriver.Chrome(chrome_options=chrome_options)
15 browser.get("https://www.tianyancha.com/search/ocD")
16
17 for opt in ch.getCookies(cookies):
18 browser.add_cookie(opt)
19
20 # 我们还可通过selenium动态渲染之后,再将html网页交给BeautifulSoup解析
21 def get_content(url):
22 browser.get(url)
23
24 bsObj = BeautifulSoup(browser.page_source,"lxml")
25 for line in bsObj.select(".name"):
26 print(line.text)
27
28 get_content("https://www.tianyancha.com/search/ocD")
29 for i in range(2,10):
30 url = "https://www.tianyancha.com/search/ocD/p%d" % i
31 get_content(url)
我们可以通过抓包,将已经登录的Cookies 字符串复制出来,然后使用以下方法将Cookies解析成selenium需要的格式
代码语言:javascript复制1 def getCookies(text):
2 result = []
3 for line in text.split(";"):
4 k ,v = line.strip().split("=")
5 result.append({"name":k,"value":v})
6
7 return result
参考文档:https://selenium-python-zh.readthedocs.io/en/latest/index.html
基本文档
要定位一个页面中的元素有多中策略和方法。你可以根据实际情况选择其中最为合适的。Selenium为定位页面元素提供了下面的这些方法:
find_element_by_id
(使用id)find_element_by_name
(使用name属性值)find_element_by_xpath
(使用XPath)find_element_by_link_text
(使用显示文本)find_element_by_partial_link_text
(使用超链接文本)find_element_by_tag_name
(使用标签名)find_element_by_class_name
(使用类名)find_element_by_css_selector
(使用CSS选择器)
要定位多个元素,除了通过id进行定位,只需将element
s
(这些元素将会以列表的形式返回)
find_elements_by_name
(使用name属性值)find_elements_by_xpath
(使用XPath)find_elements_by_link_text
(使用显示文本)find_elements_by_partial_link_text
(使用超链接文本)find_elements_by_tag_name
(使用标签名)find_elements_by_class_name
(使用类名)find_elements_by_css_selector
(使用CSS选择器)
除了上面的通用方法外,在一个页面对象进行访问操作的时候还有两个非常有用的私有方法:find_element
和find_elements
代码示例:
代码语言:javascript复制1 from selenium.webdriver.common.by import By
2
3 driver.find_element(By.XPATH, '//button[text()="Some text"]')
4 driver.find_elements(By.XPATH, '//button')
By
类可用的属性如下:
1 ID = "id"
2 XPATH = "xpath"
3 LINK_TEXT = "link text"
4 PARTIAL_LINK_TEXT = "partial link text"
5 NAME = "name"
6 TAG_NAME = "tag name"
7 CLASS_NAME = "class name"
8 CSS_SELECTOR = "css selector"
实战
http://jandan.net/ooxx 也是一个妹子图网,但是该网站是动态渲染的,使用我们第一章的方法无法爬取该网站的图片,大家可以使用本章学习的内容尝试爬取该网站。