网络爬虫开发(五)02-爬虫高级——Selenium的使用-反爬虫机制简介 & Selenium的API学习 & 实战之自动打开浏览器输入关键字进行搜索、爬取需要的数据、自动翻页 & 相关爬虫知识总结
使用Selenium实现爬虫
在使用Selenium实现爬虫之前,需要搞清楚一个问题:
- 为什么要用Selenium来做爬虫?
了解完后,还需要知道,如何实现爬虫?
- 自动打开拉勾网并搜索"前端"
- 获取所有列表项
- 获取其中想要的信息数据
为什么要用Selenium来做爬虫
目前的大流量网站,都会有些对应的反爬虫机制
例如在拉勾网上搜索传智播客:
找到对应的ajax请求地址,使用postman来测试数据:
前几次可能会获取到数据,但多几次则会出现操作频繁请稍后再试的问题
而通过Selenium可以操作浏览器,打开某个网址,接下来只需要学习其API,就能获取网页中需要的内容了!
反爬虫技术只是针对爬虫的,例如检查请求头是否像爬虫,检查IP地址的请求频率(如果过高则封杀)等手段
而Selenium打开的就是一个自动化测试的浏览器,和用户正常使用的浏览器并无差别,所以再厉害的反爬虫技术,也无法直接把它干掉,除非这个网站连普通用户都想放弃掉(12306曾经迫于无奈这样做过)
Selenium API学习
核心对象:
- Builder
- WebDriver
- WebElement
辅助对象:
- By
- Key
Builder
用于构建WebDriver对象的构造器
let driver = new webdriver.Builder() .forBrowser('chrome') .build();
其他API如下:
可以获取或设置一些Options
如需设置Chrome的Options,需要先导入Options:
const {
Options } = require('selenium-webdriver/chrome'); const options = new Options() options.addArguments('Cookie=user_trace_token=945-889e634a-a79b-4b61-9ced-996eca44b107; X_HTTP_TOKEN=7470cb9a2af2946eaad67653; _ga=GA1.2..; _gid=GA1.2..; LGUID=946-9c90e147-f443-11e8-87e4-f775ce; sajssdk_2015_cross_new_user=1; JSESSIONID=ABAAABAAAGGABCB5E0E82B87052ECD8CED0421F1D36020D; index_location_city=%E5%85%A8%E5%9B%BD; Hm_lvt_4233e74dff0ae5bd0a3d81c6ccf756e6=,; LGSID=426-da2fc57f-f449-11e8-87ea-f775ce; PRE_UTM=; PRE_HOST=www.cnblogs.com; PRE_SITE=https%3A%2F%2Fwww.cnblogs.com%2F; PRE_LAND=https%3A%2F%2Fwww.lagou.com%2Fjobs%2Flist_%25E5%2589%258D%25E7%25AB%25AF%25E5%25BC%2580%25E5%258F%2591%3Fkd%3D%25E5%2589%258D%25E7%25AB%25AF%25E5%25BC%2580%25E5%258F%2591%26spc%3D1%26pl%3D%26gj%3D%26xl%3D%26yx%3D%26gx%3D%26st%3D%26labelWords%3Dlabel%26lc%3D%26workAddress%3D%26city%3D%25E5%2585%25A8%25E5%259B%25BD%26requestId%3D%26pn%3D1; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%e1bd8cc-060451fc44d124---e1be898%22%2C%22%24device_id%22%3A%e1bd8cc-060451fc44d124---e1be898%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_referrer%22%3A%22%22%2C%22%24latest_referrer_host%22%3A%22%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%7D%7D; ab_test_random_num=0; _putrc=30FD5A7177A00E45123F89F2B170EADC; login=true; unick=%E5%A4%A9%E6%88%90; hasDeliver=0; gate_login_token=3e9da0b28b29e8e74f485b86439e1fd26fc4939d32ed2660e8421a; _gat=1; SEARCH_ID=334cf2a080f44f2fb42841f; LGRID=855-45ea2d22-f44d-11e8-87ee-f775ce; Hm_lpvt_4233e74dff0ae5bd0a3d81c6ccf756e6=; TG-TRACK-CODE=search_code') .addArguments('user-agent="Mozilla/5.0 (iPod; U; CPU iPhone OS 2_1 like Mac OS X; ja-jp) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5F137 Safari/525.20')
WebDriver
通过构造器创建好WebDriver后就可以使用API查找网页元素和获取信息了:
- findElement() 查找元素
WebElement
- getText() 获取文本内容
- sendKeys() 发送一些按键指令
- click() 点击该元素
自动打开拉勾网搜索"前端"
- 使用driver打开拉勾网主页
- 找到全国站并点击一下
- 输入“前端”并回车
const {
Builder, By, Key } = require('selenium-webdriver'); (async function start() {
let driver = await new Builder().forBrowser('chrome').build(); await driver.get('https://www.lagou.com/'); await driver.findElement(By.css('#changeCityBox .checkTips .tab.focus')).click(); await driver.findElement(By.id('search_input')).sendKeys('前端', Key.ENTER); })();
获取需要的数据
使用driver.findElement()找到所有条目项,根据需求分析页面元素,获取其文本内容即可:
const {
Builder, By, Key } = require('selenium-webdriver'); (async function start() {
let driver = await new Builder().forBrowser('chrome').build(); await driver.get('https://www.lagou.com/'); await driver.findElement(By.css('#changeCityBox .checkTips .tab.focus')).click(); await driver.findElement(By.id('search_input')).sendKeys('前端', Key.ENTER); let items = await driver.findElements(By.className('con_list_item')) items.forEach(async item => {
// 获取岗位名称 let title = await item.findElement(By.css('.p_top h3')).getText() // 获取工作地点 let position = await item.findElement(By.css('.p_top em')).getText() // 获取发布时间 let time = await item.findElement(By.css('.p_top .format-time')).getText() // 获取公司名称 let companyName = await item.findElement(By.css('.company .company_name')).getText() // 获取公司所在行业 let industry = await item.findElement(By.css('.company .industry')).getText() // 获取薪资待遇 let money = await item.findElement(By.css('.p_bot .money')).getText() // 获取需求背景 let background = await item.findElement(By.css('.p_bot .li_b_l')).getText() // 处理需求背景 background = background.replace(money, '') console.log(title, position, time, companyName, industry, money, background) }) })();
自动翻页
思路如下:
- 定义初始页码
- 获取数据后,获取页面上的总页码,定义最大页码
- 开始获取数据时打印当前正在获取的页码数
- 获取完一页数据后,当前页码自增,然后判断是否达到最大页码
- 查找下一页按钮并调用点击api,进行自动翻页
- 翻页后递归调用获取数据的函数
const {
Builder, By, Key } = require('selenium-webdriver'); let currentPageNum = 1; let maxPageNum = 1; let driver = new Builder().forBrowser('chrome').build(); (async function start() {
await driver.get('https://www.lagou.com/'); await driver.findElement(By.css('#changeCityBox .checkTips .tab.focus')).click(); await driver.findElement(By.id('search_input')).sendKeys('前端', Key.ENTER); maxPageNum = await driver.findElement(By.className('totalNum')).getText() getData() })(); async function getData() {
console.log(`正在获取第${
currentPageNum}页的数据, 共${
maxPageNum}页`) while (true) {
let flag = true try {
let items = await driver.findElements(By.className('con_list_item')) let results = [] for (let i = 0; i < items.length; i++) {
let item = items[i] // 获取岗位名称 let title = await item.findElement(By.css('.p_top h3')).getText() // 获取工作地点 let position = await item.findElement(By.css('.p_top em')).getText() // 获取发布时间 let time = await item.findElement(By.css('.p_top .format-time')).getText() // 获取公司名称 let companyName = await item.findElement(By.css('.company .company_name')).getText() // 获取公司所在行业 let industry = await item.findElement(By.css('.company .industry')).getText() // 获取薪资待遇 let money = await item.findElement(By.css('.p_bot .money')).getText() // 获取需求背景 let background = await item.findElement(By.css('.p_bot .li_b_l')).getText() // 处理需求背景 background = background.replace(money, '') // console.log(id, job, area, money, link, need, companyLink, industry, tags, welfare) results.push({
title, position, time, companyName, industry, money, background }) } console.log(results) currentPageNum++ if (currentPageNum <= maxPageNum) {
await driver.findElement(By.className('pager_next')).click() await getData(driver) } } catch (e) {
// console.log(e.message) if (e) flag = false } finally {
if (flag) break } } }
实例
第一步:安包
第二步:npm i 安装依赖
package.json
{
"name": "selenium-demo", "version": "1.0.0", "description": "", "main": "index.js", "scripts": {
"test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "dependencies": {
"selenium-webdriver": "^4.0.0-alpha.4" } }
第三步:新建demo文件
lagou.js
const {
Builder, By, Key, until } = require('selenium-webdriver'); let currentPage = 1 let maxPage; let driver = new Builder().forBrowser('chrome').build(); (async function start() {
// 自动打开百度,并搜索黑马程序员 await driver.get('https://www.lagou.com'); // 找到元素, 向里面发送一个关键字并按回车 await driver.findElement(By.css('#changeCityBox ul.clearfix > li:nth-of-type(8)')).click() await driver.findElement(By.id('search_input')).sendKeys('前端', Key.RETURN); // 在开始爬数据之前获取总页数 maxPage = await driver.findElement(By.className('totalNum')).getText() getData() })(); async function getData() {
console.log(`-------当前正在获取第${
currentPage}页的数据,共${
maxPage}页数据-------`) while (true) {
let notError = true try {
// 以下就是获取数据的代码 // 获取所有的li let items = await driver.findElements(By.css('.item_con_list .con_list_item')) // 迭代数组, 获取我们所需要的数据 let results = [] for (let i = 0; i < items.length; i++) {
let item = items[i] // console.log(await item.getText()) let title = await item.findElement(By.css('.position h3')).getText() let address = await item.findElement(By.css('.position .add em')).getText() let time = await item.findElement(By.css('.position .format-time')).getText() let jdLink = await item.findElement(By.css('.position .position_link')).getAttribute('href') let money = await item.findElement(By.css('.position .money')).getText() let background = await item.findElement(By.css('.position .li_b_l')).getText() background = background.replace(money, '') let companyName = await item.findElement(By.css('.company .company_name')).getText() let companyLink = await item.findElement(By.css('.company .company_name a')).getAttribute('href') let industry = await item.findElement(By.css('.company .industry')).getText() let tag = await item.findElement(By.css('.list_item_bot .li_b_l')).getText() let welfare = await item.findElement(By.css('.list_item_bot .li_b_r')).getText() results.push({
title, address, time, jdLink, money, background, companyName, companyLink, industry, tag, welfare }) } // 爬取到了一页数据 console.log(results) currentPage++; if (currentPage <= maxPage) {
// 找到下一页按钮 点它! await driver.findElement(By.className('pager_next')).click() // 递归获取数据 getData() } } catch (e) {
// console.log(e.message) if (e) notError = false } finally {
if (notError) break } } }
第四步:运行测试
node .\helloworld.js
此时,自动新开启浏览器并进行爬虫数据获取
第4章 课程总结
爬虫神通广大,用途非常广泛,主要的目标是为了实现自动化程序,解放程序员的双手
帮助程序员自动获取一些数据,测试一些软件,甚至自动操作浏览器做很多事情
也不乏有些不法分子拿爬虫做一些违法的事情,在此老师希望大家学会爬虫使用在正道上,获取一些我们需要的数据来进行分析
同时,在爬取目标网站之前,建议大家浏览该网站的robots.txt,来确保自己爬取的数据在对方允许范围之内
课程内容涵盖:
- 爬虫简介
- 爬虫的意义
- 各行各业的爬虫
- 使用http模块爬取数据
- http模块发送请求
- 使用cheerio库进行DOM解析
- 一个服务端解析HTML的库,与jQuery API设计相同
- 使用download库进行文件下载
- 使用TypeScript面向对象思想进行爬虫基础库的封装
- 使用Selenium实现爬虫
- 使用Selenium自动翻页
自动操作浏览器做很多事情
也不乏有些不法分子拿爬虫做一些违法的事情,在此老师希望大家学会爬虫使用在正道上,获取一些我们需要的数据来进行分析
同时,在爬取目标网站之前,建议大家浏览该网站的robots.txt,来确保自己爬取的数据在对方允许范围之内
课程内容涵盖:
- 爬虫简介
- 爬虫的意义
- 各行各业的爬虫
- 使用http模块爬取数据
- http模块发送请求
- 使用cheerio库进行DOM解析
- 一个服务端解析HTML的库,与jQuery API设计相同
- 使用download库进行文件下载
- 使用TypeScript面向对象思想进行爬虫基础库的封装
- 使用Selenium实现爬虫
- 使用Selenium自动翻页
学习不是百米冲刺,而是一场马拉松,现在所学只是起点,更多的是需要大家找到学习方法,不断的学习提升自己,一起加油!
到此这篇网络爬虫开发(五)02-爬虫高级——Selenium的使用-反爬虫机制简介 & Selenium的API学习 & 实战之自动打开浏览器输入关键字进行搜索、爬取需要的数据、自动翻页 & 相关爬虫知识总结的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/hd-api/10721.html