爬虫-浏览器自动化
什么是selenium
selenium是浏览器自动化测试框架,原本用于网页测试。但到了爬虫领域,它又成为了爬虫的好帮手。有了 selenium,我们便不再需要判断网页数据加载的方式,只要让 selenium 自动控制浏览器,就像有双无形的手,控制着你的鼠标和键盘,自动地帮你干活。爬取数据?自动抢票?这些当然统统都不在话下。
安装selenium
和安装python的第三方库是一样的
pip install selenium
selenium还需要安装相应的浏览器驱动才能控制浏览器。强烈推荐使用Chorme浏览器。
查看自己电脑上的浏览器版本,依次点击浏览器右上角的 三个点 - 帮助 - 关于 Google Chrome。
将下载的对应版本的的 chromedriver 解压缩,Windows 系统得到 chromedriver.exe,这个就是我们需要的浏览器驱动。我们要将它放到 Python 所在安装目录里。
为了验证驱动是否安装成功,Windows 系统在的 命令行 或者 Anaconda Prompt 中输入 chromedriver 命令,如果出现类似下图所示的内容,就证明驱动已经安装成功了。
打开浏览器
来看下如何用selenium打开Chrom浏览器
# 从 selenium 中导入 webdriver(驱动) from selenium import webdriver # 选择 Chrome 浏览器并打开 browser = webdriver.Chrome()
获取数据
# 从 selenium 中导入 webdriver(驱动) from selenium import webdriver # 选择 Chrome 浏览器打开 browser = webdriver.Chrome() # 打开网页 browser.get('https://wpblog.x0y1.com') # 关闭浏览器 browser.quit()
browser 是我们实例化的浏览器。我们将网址传给 browser 对象的 get() 方法,即可打开对应的网页。最后调用 quit() 方法将浏览器关闭。
我们的目的是获取数据,接下来让我们用 browser 对象的 page_source 属性来获取网页的源代码。值得注意的是,用 selenium 获取的网页源代码是数据加载完毕后最终的源代码,也就是网页加载后通过 API 获取的数据也在这个源代码中。
因此,我们就不用再区分要爬取的网页是静态网页还是动态网页了,在 selenium 眼里统统都一样。
代码 | 作用 |
browser = webdriver.Chrome() | 打开Chrome浏览器 |
browser.get("网址") | 打开网页 |
browser.page_source | 获取网页源代码 |
browser.quit() | 关闭浏览器 |
处理数据
我们来看看如何用 selenium 处理数据。我们以获取博客的 h1 元素为例。
from selenium import webdriver browser = webdriver.Chrome() browser.get('https://wpblog.x0y1.com') h1 = browser.find_element(by='tag name', value='h1') # 上面的代码也可以写成 # h1 = browser.find_element('tag name', 'h1') print(h1.text) browser.quit()
方法 | 作用 |
find_element(by = 'tag name', value=...) | 通过标签查找元素 |
find element(by = 'class name', value=...) | 通过 class 属性名查找元素 |
find element(by = 'id', value=...) | 通过 id 查找元素 |
find element(by = 'name', value=...) | 通过 name 属性查找元素 |
find element(by = 'Link text', value=...) | 通过链接文本查找元素 |
find element(by = 'partial link text', value=...) | 通过链接的部分文本查找元素 |
这些方法找到的元素(返回值)都是 WebElement 对象,它和 BeautifulSoup 里的 Tag 对象一样,也有一个 text 属性,一样也是获取元素里的文本内容。
BeautifulSoup 中通过 select() 方法查找所有被所传入的 CSS 选择器选中的元素。刚才介绍的那些方法都是查找第一个符合条件的元素,接下来我们来看看 selenium 中查找所有符合条件的元素的方法。
这些方法非常简单,直接把 find_element() 方法改成 find_elements() 方法即可:
方法 | 作用 |
find_elements(by = 'tag name', value=...) | 通过标签查找元素 |
find elements(by = 'class name', value=...) | 通过 class 属性名查找元素 |
find elements(by = 'id', value=...) | 通过 id 查找元素 |
find elements(by = 'name', value=...) | 通过 name 属性查找元素 |
find elements(by = 'Link text', value=...) | 通过链接文本查找元素 |
find elements(by = 'partial link text', value=...) | 通过链接的部分文本查找元素 |
比如获取网页源代码中所有的a元素
from selenium import webdriver browser = webdriver.Chrome() browser.get('https://wpblog.x0y1.com') # 注意下面是 elements a_tags = browser.find_elements('tag name', 'a') for tag in a_tags: print(tag.text) browser.quit()
值得一提的是,WebElement 对象也可以调用 selenium 查找元素的方法。这样就和 BeautifulSoup 中的 Tag 对象一样,可以一层一层的查找元素,直到找到为止。
BeautifulSoup 的原理是将网页源代码的字符串形式解析成 BeautifulSoup 对象,然后通过 BeautifulSoup 对象 的属性和方法提取出我们需要的数据。发现没有?BeautifulSoup 只需要一个网页源代码的字符串形式即可。
之前我们都是使用 requests 库获取网页源代码,并通过 text 属性取得其字符串形式。而 selenium 获取网页后的 page_source 属性值正是字符串格式的!
以上面获取博客网页源代码中所有的 a 元素 为例,加上 BeautifulSoup 可以这样写:
from selenium import webdriver from bs4 import BeautifulSoup browser = webdriver.Chrome() browser.get('https://wpblog.x0y1.com') # 用 BeautifulSoup 解析网页源代码 soup = BeautifulSoup(browser.page_source, 'html.parser') a_tags = soup.select('a') for tag in a_tags: print(tag.text) browser.quit()
我写了一个两者结合爬取豆瓣读书的代码
import time from selenium import webdriver from bs4 import BeautifulSoup browser = webdriver.Chrome() browser.get("https://book.douban.com/top250/") time.sleep(2) #soup = BeautifulSoup(res.text, 'html.parser') soup = BeautifulSoup(browser.page_source, 'html.parser') #print(soup) # 所有书名所在元素 book_name_tags = soup.select("a") #print(book_name_tags) book_names = [] for book_name in book_name_tags: name = book_name.attrs if 'title' in name: book_names.append(name['title']) # 所有书籍信息所在元素 book_info_tags = soup.find_all('p', class_="pl") for i in range(len(book_names)): name = book_names[i] author = book_info_tags[i].text.split('/')[0] publisher = book_info_tags[i].text.split('/')[-3] print("%s / %s / %s" % (name, author, publisher)) browser.quit()
返回的结果如下:
红楼梦 / [清] 曹雪芹 著 / 人民文学出版社
活着 / 余华 / 作家出版社
1984 / [英] 乔治·奥威尔 / 北京十月文艺出版社
哈利·波特 / J.K.罗琳 (J.K.Rowling) / 人民文学出版社
三体全集 / 刘慈欣 / 重庆出版社
百年孤独 / [哥伦比亚] 加西亚·马尔克斯 / 南海出版公司
飘 / [美国] 玛格丽特·米切尔 / 译林出版社
动物农场 / [英] 乔治·奥威尔 / 上海译文出版社
三国演义(全二册) / [明] 罗贯中 / 人民文学出版社
房思琪的初恋乐园 / 林奕含 / 北京联合出版公司
福尔摩斯探案全集(上中下) / [英] 阿·柯南道尔 / 1981-8
白夜行 / [日] 东野圭吾 / 南海出版公司
小王子 / [法] 圣埃克苏佩里 / 人民文学出版社
安徒生童话故事集 / (丹麦)安徒生 / 人民文学出版社
天龙八部 / 金庸 / 生活·读书·新知三联书店
撒哈拉的故事 / 三毛 / 哈尔滨出版社
呐喊 / 鲁迅 / 人民文学出版社
邓小平时代 / 【美】傅高义 (Ezra.F.Vogel) / 生活·读书·新知三联书店
悉达多 / [德] 赫尔曼·黑塞 / 天津人民出版社
杀死一只知更鸟 / [美] 哈珀·李 / 译林出版社
明朝那些事儿(1-9) / 当年明月 / 中国海关出版社
失踪的孩子 / [意] 埃莱娜·费兰特 / 人民文学出版社
新名字的故事 / [意] 埃莱娜·费兰特 / 人民文学出版社
野草 / 鲁迅 / 人民文学出版社
沉默的大多数 / 王小波 / 中国青年出版社
控制浏览器
我们要想登录博客,那必须具备登录的动作,再学习两个方法,分别是:click() 和 send_keys()
方法 | 作用 |
click() | 点击元素 |
send_keys() | 模拟按键输入 |
看下其在代码中的应用
from selenium import webdriver import time browser = webdriver.Chrome() # 打开博客 browser.get('https://wpblog.x0y1.com') # 找到登录按钮 login_btn = browser.find_element('link text', '登录') # 点击登录按钮 login_btn.click() # 等待 2 秒钟,等页面加载完毕 time.sleep(2) # 找到用户名输入框 user_login = browser.find_element('id', 'user_login') # 输入用户名 user_login.send_keys('codetime') # 找到密码输入框 user_pass = browser.find_element('id', 'user_pass') # 输入密码 user_pass.send_keys('shanbay520') # 找到登录按钮 wp_submit = browser.find_element('id', 'wp-submit') # 点击登录按钮 wp_submit.click() # 找到 Python 分类文章链接 python_cat = browser.find_element('css selector', 'section#categories-2 ul li a') # 点击该分类 python_cat.click() # 找到跳转的页面中的所有文章标题元素 titles = browser.find_elements('css selector', 'h2.entry-title a') # 找到标题元素中内含的链接 links = [i.get_attribute('href') for i in titles] # 依次打开 links 中的文章链接 for link in links: browser.get(link) # 获取文章正文内容 content = browser.find_element('class name', 'entry-content') print(content.text) browser.quit()