栏目分类:
子分类:
返回
文库吧用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
文库吧 > IT > 软件开发 > 后端开发 > Ruby开发

基于ruby+selenium的第三方广告检测

Ruby开发 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

基于ruby+selenium的第三方广告检测

本文的工程目的是使用ruby编写一个脚本文件,实现对网页中第三方广告的检测和统计。
项目源代码:https://github.com/vito0705/selenium_vito

本文主要内容
  • 一.项目分析

    • 项目目的

    • 项目要求

    • 项目解决思路

  • 二.环境配置

    • Linux下环境配置

    • Windows下环境配置

  • 三.程序编写

    • (一)加载库文件

    • (二)初始化部分

    • (三)网页检测部分

    • (四)代码执行部分

    • 项目设计思路

    • 代码实现

  • 四.脚本使用

  • 五.总结

一.项目分析
项目目的

对页面中的第三方广告进行检测,找出其中隐藏的广告网页并将数据记录下来。

项目要求
  • 检测所有广告及广告的域并记录下来

  • 统计所有广告的数目及其中隐藏广告的数目

  • 以表格形式保存数据

项目解决思路
  • 第三方广告都在网页中的iframe标签中,需要从iframe标签中获取所需的数据

  • 根据需要,我们选择selenium作为web自动化测试工具

  • 数据需要保存在表格中,我们选择spreadsheet这个gem来实现相关功能

二.环境配置

Linux和windows下均可以使用这个脚本,但对于环境配置略有不同。

Linux下环境配置1.安装ruby

可以参考这篇文章中使用rvm管理ruby的方式安装,要求ruby版本大于等于2.0,具体安装不作更多说明。

2.安装ruby版本的selenium

在terminal中执行:

gem install selenium-webdriver

selenium-webdriver的Github源码地址

3.安装spreadsheet:
gem install spreadsheet

spreadsheet的GitHub源码地址

4.安装selenium浏览器驱动driver
  • Chrome

    • 版本对应:ChromeDriver与Chrome版本的对应关系

    • driver下载:ChromeDriver - WebDriver for Chrome

  • Firefox

    • driver下载及版本对应:https://github.com/mozilla/geckodriver/releases

根据自己的浏览器版本,选择对应的selenium浏览器驱动版本driver进行下载解压,将下载解压好的driver文件移动到/usr/bin/文件夹下即可。

以上四步,是linux下运行程序必要的环境配置,务必保证每一步的正确安装。

Windows下环境配置

windows下的环境配置与Linux下略有不同,但思路是相通的。

1.安装ruby

按照这篇文章《Ruby 安装 - Windows》安装ruby即可,记得勾选Add Ruby executables to your PATH这一项。同样,要求ruby版本大于等于2.0。

2.安装ruby版本的selenium

在cmd中执行:

gem install selenium-webdriver

selenium-webdriver的Github源码地址

3.安装spreadsheet:
gem install spreadsheet

spreadsheet的GitHub源码地址ß

4.安装selenium浏览器驱动driver
  • Chrome

    • 版本对应:ChromeDriver与Chrome版本的对应关系

    • driver下载:ChromeDriver - WebDriver for Chrome

  • Firefox

    • driver下载及版本对应:https://github.com/mozilla/geckodriver/releases

根据自己的浏览器版本,选择对应的selenium浏览器驱动版本driver进行下载解压,将下载解压好的driver文件放在对应的浏览器安装目录下,之后需要对Windows环境变量进行配置。
Windows下需要在系统变量的path变量中添加exe文件的位置,配置环境变量可参考这篇文章:Win7怎样添加环境变量,注意路径中不要有中文。

同样,这四步也是Windows下必备的环境配置。但在自己的测试过程中,由于一些安全问题,Windows下的chrome始终没有调通,但Firefox是可以使用的。

三.程序编写
项目设计思路
  1. 为了能使脚本检测大量网站,我们使用三个文件,一个txt文件,一个xls表格文件和包含所有逻辑功能的ruby文件。

  • weburl.txt:在文件中,每个网址占一行,ruby文件会依次按行读取此文件中的网址进行检测

  • ad_file.xls:用于保存数据,最终的数据会写入这个文件

  • detection_ad.rb:所有的数据逻辑处理均包含在这个文件中,负责检测页面中的第三方广告。

  • 第三方广告都在iframe标签中,我们的目的是找到这些iframe标签中的src,即就是第三方广告的网址。因此我们可以将思路转变为:首先通过selenium获取网页的源代码,之后通过ruby正则表达式来实现对关键信息的提取。

  • 对于selenium和spreadsheet两个gem的使用,我们不作过多解释,可以参考以下两篇文章,给出了两个gem的基本使用方法。

    • selenium对浏览器的简单操作(webdriver+ruby)

    • rails导出excel插件 spreadsheet的标准使用

    代码实现

    代码内容我们分成将四部分来分别说明。

    (一)加载库文件
    require 'rubygems'  require 'selenium-webdriver' require 'spreadsheet'
    (二)初始化部分
    # 存放网址的文件web_file = "weburl.txt"# 创建excel表格实例Spreadsheet.client_encoding = "UTF-8" excel_fil = Spreadsheet::Workbook.new  
    sheet = excel_fil.create_worksheet :name => "ads_show"# 创建浏览器driver实例# driver = Selenium::WebDriver.for :chromedriver = Selenium::WebDriver.for :firefox# 创建三个全局变量# web_num:excel表单中的行数# all_ads_num:所有网页的广告总数# hide_ads_num:所有网页的隐藏广告总数$web_num = 1$all_ads_num = 0$hide_ads_num = 0
    (三)网页检测部分

    这部分的功能是检测一个网页中的所有第三方广告,找到广告的域并统计广告的数量,进一步需要分离出页面中隐藏的第三方广告。
    我们将这部分定义为一个方法:search_ads(driver, web_url_para, sheet),这个方法要求三个参数:

    • driver:已经创建的浏览器driver实例,如driver = Selenium::WebDriver.for :firefox

    • web_url_para:待检测网页网址url

    • sheet:已经创建的excel表单实例,如sheet = excel_fil.create_worksheet :name => "ads_show"

    接下来会从多个模块来介绍这一部分内容。

    功能块一
        web_url = web_url_para    #--------------------------------------------------------
        #web_url_domain:the domian of the web page
        #--------------------------------------------------------
        web_url_domain_raw = web_url.match(/https?://https://www.wk8.com.cn/skin/sinaskin/image/nopic.gif/.*?/)
        web_url_domain = web_url_domain_raw[1]

    这部分使用正则匹配获得待检测网址的域,有两个重要的点需要说明。

    1.不同的域

    所谓第三方,指的是在iframe中嵌入的网页的域与当前网页的域不同。那么什么是域呢?在我之前介绍跨域解决方案rack-cors文章里,举了这样一个例子:

    那么什么是同源?我们知道,URL由协议、域名、端口和路径组成,如果两个URL的协议、域名和端口相同,则表示他们同源。

    我们用一个例子来说明:
    URL: http://www.example.com:8080/script/jquery.js
    在这个url中,各个字段分别代表的含义:
    http://——协议
    www——子域名
    example.com——主域名
    8080——端口号
    script/jquery.js——请求的地址
    当协议、子域名、主域名、端口号中任意一各不相同时,都算不同的“域”。不同的域之间相互请求资源,就叫跨域。

    因此,需要获得当前网页的域,来和iframe中的网址作对比,来判断是否属于第三方。

    2.MatchData对象的分组捕获

    这里不对ruby中的正则表达式的语法进行详述,仅对其MatchData对象中的分组捕获相关的几点做简单的说明。

    • match方法

      • 可以双向使用match方法,即正则表达式和字符串对象均可以响应match方法。match方法会将字符串参数转换为正则表达式

      • match与=~的区别:正则表达式匹配后返回值不同,=~返回字符串匹配中匹配的开始位置的数字索引,而match则返回MatchData实例:

        2.2.7 :017 > "The alphabet starts with abc" =~ /abc/
         => 25 2.2.7 :018 > /abc/.match("The alphabet starts with abc")
         => #
    • MatchData对象

      • 正则表达式通过圆括号指定捕获(capture)。当一个字符串和模式之间进行正则匹配测试时,通常是想使用字符串,或者更常见的是用字符串的一部分完成一些操作。捕获表示法让用户可以从能够匹配特殊子模式的字符串中,抽取和保存字符子串。

      • 从MatchData对象中得到捕获结果的一个方式是直接通过数组的方式索引对象:0索引会返回匹配的整个字符串;从1开始往后,n的索引会基于从左边的括号开始计数,返回第n个捕获结果。关于“从左开始计数圆括号”的周期性,用一个例子来说明:

        a=/((a)((b)c)(d)?)/.match("abce")
            => # 
        a[0]                => "abc"a[1]                => "abc" a[2]                => "a" a[3]                => "bc" a[4]                => "b" a[5]                => nil        (不匹配)
        a[6]                => nil        (超出范围)
        a[-2]               => "b"

        可以肯定的是,上式中,从左边开始计数的成对圆括号之间匹配的结果,与结果严格对应。

      • 当正则表达式通过match方法匹配时,返回一个MatchData对象;当正则表达式不匹配时,返回nil

        2.2.7 :019 > /abc/.match("abcd")
         => # 
        2.2.7 :020 > /abc/.match("bcd")
         => nil
      • 分组捕获

    功能块二
        driver.get web_url
        sleep 3
        #--------------------------------------------------------
        #get ...