网络爬虫开发(五)02-爬虫高级——Selenium的使用-反爬虫机制简介 & Selenium的API学习 & 实战之自动打开浏览器输入关键字进行搜索、爬取需要的数据、自动翻页 & 相关爬虫知识总结

网络爬虫开发(五)02-爬虫高级——Selenium的使用-反爬虫机制简介 & Selenium的API学习 & 实战之自动打开浏览器输入关键字进行搜索、爬取需要的数据、自动翻页 & 相关爬虫知识总结

使用Selenium实现爬虫

在使用Selenium实现爬虫之前,需要搞清楚一个问题:

  • 为什么要用Selenium来做爬虫?

了解完后,还需要知道,如何实现爬虫?

  1. 自动打开拉勾网并搜索"前端"
  2. 获取所有列表项
  3. 获取其中想要的信息数据

为什么要用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=20191130095945-889e634a-a79b-4b61-9ced-996eca44b107; X_HTTP_TOKEN=7470c50044327b9a2af2946eaad67653; _ga=GA1.2.2111156102.1543543186; _gid=GA1.2.1593040181.1543543186; LGUID=20181130095946-9c90e147-f443-11e8-87e4-525400f775ce; sajssdk_2015_cross_new_user=1; JSESSIONID=ABAAABAAAGGABCB5E0E82B87052ECD8CED0421F1D36020D; index_location_city=%E5%85%A8%E5%9B%BD; Hm_lvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1543543186,1543545866; LGSID=20181130104426-da2fc57f-f449-11e8-87ea-525400f775ce; 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%221676257e1bd8cc-060451fc44d124-9393265-2359296-1676257e1be898%22%2C%22%24device_id%22%3A%221676257e1bd8cc-060451fc44d124-9393265-2359296-1676257e1be898%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=3e9da07186150513b28b29e8e74f485b86439e1fd26fc4939d32ed2660e8421a; _gat=1; SEARCH_ID=334cf2a080f44f2fb42841f473719162; LGRID=20181130110855-45ea2d22-f44d-11e8-87ee-525400f775ce; Hm_lpvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1543547335; 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() 点击该元素

在这里插入图片描述

自动打开拉勾网搜索"前端"

  1. 使用driver打开拉勾网主页
  2. 找到全国站并点击一下
  3. 输入“前端”并回车
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)
  })
})();

自动翻页

思路如下:

  1. 定义初始页码
  2. 获取数据后,获取页面上的总页码,定义最大页码
  3. 开始获取数据时打印当前正在获取的页码数
  4. 获取完一页数据后,当前页码自增,然后判断是否达到最大页码
  5. 查找下一页按钮并调用点击api,进行自动翻页
  6. 翻页后递归调用获取数据的函数
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,来确保自己爬取的数据在对方允许范围之内

课程内容涵盖:

  1. 爬虫简介
  2. 爬虫的意义
    • 各行各业的爬虫
  3. 使用http模块爬取数据
    • http模块发送请求
  4. 使用cheerio库进行DOM解析
    • 一个服务端解析HTML的库,与jQuery API设计相同
  5. 使用download库进行文件下载
  6. 使用TypeScript面向对象思想进行爬虫基础库的封装
  7. 使用Selenium实现爬虫
  8. 使用Selenium自动翻页

自动操作浏览器做很多事情

也不乏有些不法分子拿爬虫做一些违法的事情,在此老师希望大家学会爬虫使用在正道上,获取一些我们需要的数据来进行分析

同时,在爬取目标网站之前,建议大家浏览该网站的robots.txt,来确保自己爬取的数据在对方允许范围之内

课程内容涵盖:

  1. 爬虫简介
  2. 爬虫的意义
    • 各行各业的爬虫
  3. 使用http模块爬取数据
    • http模块发送请求
  4. 使用cheerio库进行DOM解析
    • 一个服务端解析HTML的库,与jQuery API设计相同
  5. 使用download库进行文件下载
  6. 使用TypeScript面向对象思想进行爬虫基础库的封装
  7. 使用Selenium实现爬虫
  8. 使用Selenium自动翻页

学习不是百米冲刺,而是一场马拉松,现在所学只是起点,更多的是需要大家找到学习方法,不断的学习提升自己,一起加油!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Selenium是一个用于自动浏览器操作的工具,可以模拟用户在浏览器中的行为。然而,一些网站会采取爬虫的措施,来阻止Selenium使用。为了应对这些爬虫措施,可以使用一些方法来爬虫。 其中一个常见的爬虫手段是检测浏览器的User-Agent头部信息,因为Selenium的默认User-Agent是可被识别的。为了应对这种情况,可以使用Selenium的`ChromeOptions`类来修改User-Agent,通过修改User-Agent来伪装成普通浏览器。在引用的代码示例中,使用了`options.add_argument('--user-agent=Mozilla/5.0 HAHA')`来替换User-Agent头部信息。 此外,还有其他一些常见的爬虫手段,比如基于身份识别、基于爬虫行为和基于数据加密等。如果遇到这些爬虫手段,可以根据具体情况采取相应的应对措施。例如,在基于身份识别进行爬的情况下,可以通过模拟登录来获取合法的访问权限;在基于爬虫行为进行爬的情况下,可以通过调整访问频率或添加随机延时来模拟真实用户的行为;在基于数据加密进行爬的情况下,可以使用Selenium来执行JavaScript代码来解密数据。 综上所述,针对不同的爬虫手段,可以采取相应的应对措施来爬虫。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Python爬虫第二课 Selenium介绍和爬技术](https://blog.csdn.net/fegus/article/details/124447201)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值