爬虫之登陆验证

原创 2016年11月25日 10:49:55


运行爬虫抓取某些网站的时候,经常会碰到需要登陆验证(输入账号、密码)之后才能获取数据的情况。那么问题来了,如何完成登陆验证呢?下面以itunes为例大概总结两种方法。主要使用工具为python/java、selenium、phantomjs或firefox/chrome等浏览器.

一 python urllib2库的简单介绍

本人之前主要使用java进行外部数据获取,用的工具包httpclient。基本没用过python-urllib2库,google了一下,发现两个特别靠谱的参考资料:

1. csdn中 @请叫我汪海的《urllib2的使用细节与抓站技巧》,学习了一下,发现还挺好使的,简单明了。

2. 另外一个可参考的资料是《urllib2 - The Missing Manual :HOWTO Fetch Internet Resources with Python》跟上面内容有重复,也有补充。

看完这两个基本就能大概掌握获取网页的用法啦,这里强调以下几点。

a. 特别注意要发送的headers。文中已经提到了User-Agent 、Content-Type 、application/xml 、application/json 、application/x-www-form-urlencoded,很多时候数据取不出来与这些header有关系。httpheader可以参照wiki《List of HTTP header fields》,当年瞎摸索的时候,没注意看好这些headers,吃了不少亏。

b. 注意使用debug模式来监测爬取过程中的信息,尤其是报错信息和报错码。错误码也请参照wiki《List_of_HTTP_status_codes》,充分利用这些错误码,也能缩短调试时间。当然,多打印try-except也是一种有效的调试手段。


二、登陆之数据包分析

工具: python-urllib2   |  firefox+firebug或者chrome,用浏览器打开登陆页面之后,按F12键会默认打开开发者工具或者启动firebug,点击network监听数据包,下面以itune的登陆举一个例子。


1. 在浏览器中输入itunes的登陆地址:https://itunesconnect.apple.com/itc/static/login?view=1&path=%2FWebObjects%2FiTunesConnect.woa,同时按F12启动firebug进行网络监听.


点击“网络” --》 ”全部“ ,可以看到所有加载的页面数据,包括html/图像/css/js等。

点击“html”,全部里边显示的信息太多,可以先只看html,这里边出现的html-url通常是我们需要用urllib2实际请求的页面。

下面是firefox+firebug显示的页面


而这个是chrome的开发者工具显示的页面


不同的工具监测到数据包会有差别,上面两个对比看一下,大概估计实际需要get的url,就只有2个。


2. 我们点开查看其中一个,重点关注一下相应的参数、头信息。(头信息中的Cookie字段和 后面的cookies表单中的内容是一致的)。

头信息又分为请求头信息和响应头信息。urlopen需要提交的头信息可能是请求头信息中的一部分。响应头信息中的字段可能会在访问下一个页面的时候用到。


3. 账号密码的输入通常都会涉及到一个post请求,我们可以输入一个错误的账号、密码试试

(输入正确的用户信息,会导致这个页面跳转,控制台会全部刷新,之前的访问路径就丢了)。

点击进去,可以看到需要提交的参数(账号、密码等)、额外的头文件、cookie等。

所以,itunes的登陆大概分为上面三步:

先 get :  https://itunesconnect.apple.com/itc/static/login?view=1&path=%2FWebObjects%2FiTunesConnect.woa

后 get :  https://idmsa.apple.com/appleauth/auth/signin?widgetKey=22d448248055bab0dc197c6271d738c3

最后post : https://idmsa.apple.com/appleauth/auth/signin


下面附上上面3步骤对应的python代码,早期的话,这种方式直接就能完成itunes的登陆,也适用于大部分简单的网站。

                # 记录全过程的cookie
                cj=cookielib.CookieJar() 
                opener=urllib2.build_opener(urllib2.HTTPCookieProcessor(cj)) 
                urllib2.install_opener(opener) 
                # 前两步get
                response1 = urllib2.urlopen('<span style="font-size:14px;">https://itunesconnect.apple.com/itc/static/login?view=1&path=%2FWebObjects%2FiTunesConnect.woa</span>').read()
                response2 = urllib2.urlopen('https://idmsa.apple.com/appleauth/auth/signin?widgetKey=22d448248055bab0dc197c6271d738c3').read()
                # 第三步post
                
                login_data = {'accountName':self.account, 'password': self.password, 'rememberMe': 'false'}# 账号和密码
                login_url = "<span style="font-size:14px;">https://idmsa.apple.com/appleauth/auth/signin</span>"
                head = {'Content-Type': 'application/json',# 头部信息
                        'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36'}
         
                loginData = urllib.urlencode(login_data)    
                request = urllib2.Request(login_url, loginData, head) # 获取网页
                try:
                    response = urllib2.urlopen(request, timeout = 6)
                except:
                    print response.read()
                    sys.exit(1)
                # 完成登陆,打印cookie信息
在itunes网站升级之后,上面这种方法就不行了,因为itunes添加了新的验证机制,通常是需要爬虫使用额外的header。但难点在于这些header的构造非常复杂,中间会经过一系列js的运算,这个时候要爬虫去计算出这些header值就变得非常困难。例如itunes升级之后,就需要提交一个header叫“X-Apple-I-FD-Client-Info”,而这个header我们算不出来。


总结

通过数据包分析进行登录验证的优缺点如下。

优点:执行速度快。

缺点:抓包分析比较费时,有的时候不确定哪些header是必须的,另外有些header算不出来。

在验证分析需要的header取不到的情况下,就可以考虑使用浏览器模拟点击的方式,跳过数据包分析。

三、登陆之模拟点击

工具:python/java + selenium + firefox/chrome/phantomjs

(1)windows开发环境搭建

默认已经安装好了firefox

  • 安装pip

pip是一个python的软件包管理工具,用于自动下载并安装、更新python包,python3之后的某些版本已经自带pip,在python 2.7之前的话,需要自己安装,现在的安装方法已经非常简单,直接查看官方doc:http://pip.readthedocs.org/en/stable/installing/,下载get-pip.py并执行python get-pip.py即可一键安装。其他方法可参考《怎么在windows下安装pip。为了便于使用,最好添加到系统变量PATH中。

  • 安装phantomjs

从官网下载windows版本的压缩包(http://phantomjs.org/download.html)。下载之后,直接解压到本地。建议使用最新版phantomjs-2.0.0-windows.zip,因为有些情况下phantomjs不能正确的解析仅仅是因为版本兼容性不好,这种bug基本无解,绕来绕去最终换过版本就好了。

  • 安装selenium

如果是python环境,安装好pip之后,直接使用

pip install selenium
pip install --upgrade selenium # 升级到最新版本

如果是java环境,下载一个完整的selenium-server-standalone-2.48.2.jar包即可,这个包很大,已经包含了所有依赖包和各种driver如(htmlunit driver之类的)

(2)linux(debian)开发环境搭建

  • 安装firefox

版权问题,debian自带的浏览器并不是firefox。如果想在debian环境下,使用firefoxDriver进行模拟点击,就必须先安装firefox。我在debian服务器上试了几种方法均失败,不过下面还是说一下找到的几种方法。

方法一:从firefox官网下载linux版之后,直接解压firefox

方法二:命令行安装。

参考

1. 《Install the Real Firefox on Debian 7》(可能需要翻墙)

2.How to install the real Firefox on Debian?》里边讲了两种方法

3. 《Tutorial: How to use Headless Firefox for Scraping in Linux》靠谱

  • 安装phantomjs

目前phantomjs在linux环境下并没有稳定的可执行文件需要,自行编译

a. 先安装依赖包

sudo apt-get install build-essential g++ flex bison gperf ruby perl \ 
             libsqlite3-dev libfontconfig1-dev libicu-dev libfreetype6 libssl-dev \ 
             libpng-dev libjpeg-dev python libx11-dev libxext-dev
b. 编译,大约需要半个小时,请耐心等待

git clone git://github.com/ariya/phantomjs.git 
cd phantomjs 
git checkout 2.0 
./build.sh

具体可参考phantomjs的官网:http://phantomjs.org/build.html

  • 安装selenium

跟windows一样简单,直接pip install selenium就搞定,前提是pip可用。

(3) selenium的使用介绍

selenium是一个自动化测试工具,支持多种编程语言java/python/javascript/ruby/php/C#/perl。我们在爬虫中主要用于抓取动态页面时模拟浏览器行为,绕过后台执行js的复杂过程,用“所见即所得”的方式进行页面点击、截屏、悬浮窗拖拽等。之前中文资料比较少,加上selenium 2.0和1.0巨大的区别,csdn上的中文博客大多不好使。刚搜了一下,好像有些中文社区和更正式一点的博客,感觉不错,先贴出来:

1. 《webDriver中文教程 & 中文社区》貌似是今年的,比较官方的样子,还没细看

2. 《Selenium Webdriver 简易教程

3.  官网的webdriver使用文档,也属于入门级别,有些复杂操作需要从其他有经验的使用者的博客里边略窥一二。

4.《The Selenium Browser Automation Project》介绍比较全面。

 下面主要介绍一下可能遇到的坑,别人的经验可以参考《记录我遇到的使用selenium让人摸不着头脑的问题 》,下面是我碰过几次的
  • iframe & window

Selenium2(webdriver)在使用get(url)方法打开一个网页的时候,是不会继续加载里面的iframe中的页面源码,这与selenium 1的使用不同。当碰到有些元素不可选的时候,可以使用开发者工具查看是否有iframe元素。

# 切换iframe
driver.switch_to.frame("frameName") # 还有其他api
# 切换window
for handle in driver.window_handles:
   driver.switch_to.window(handle)


  • 不同的webdriver

     官网已经有使用webdriver的优缺点的比较,例如firefox通常比ie快,而无界面的HtmlUnitDriver通常会比firefox快,但对js的支持并不是那么好。并且不同driver对xpath语法的支持也不一样。

    就个人使用经验来看,即便是同样的webdriver差别还是有点大的。例如在某些firefox的版本是可以抓取数据的,但在另外一些版本就不行,selenium在这两年的演化过程中,中途出现过对最新firefox各种报错、但对老版本firefox就正常,以及对老phantomjs不能抓取,最新版本phantomjs就OK的情况。当遇到各种很诡异的关于浏览器不能抓取问题的时候,需要考虑尝试不同的webdriver,以避开selenium对个别型号的浏览器支持不良的情况。

  • 隐式等待与显示等待

    当网页上有ajax等动态元素时,webdriver.get(url)只会等待html和js文件加载完成,但不一定会等待js生成的元素都出现在页面源码中。使用xpath或者css选择器的时候,如果js产生的代码没有加载完成,就会报错,这种我们用开发者工具能发现的元素,但webdriver找不到的情况,通常都是因为等待时间不够造成的。通常有两种方法:

第一种隐式等待,优点是想法简单,缺点是不同的页面需要的加载时间不同,为了保证数据正确,需要取一个最大的等待时间,拖慢代码执行效率。python中的源码如下

# 每次获取页面都设置10秒钟的超时时间
driver.implicitly_wait(10)


第二种是显示等待。用于指定等待到页面加载到某些为真的可控条件,例如出现某个元素之后,就认为需要的页面内容已经加载完成了,python代码如下:

# 构建WebDriverWait,设置最大超时时间是30秒

wait = WebDriverWait(driver, 30)

# 等待页面出现id=authFrame的元素出现,一旦出现就进入下一步

wait.until(EC.frame_to_be_available_and_switch_to_it((By.ID,'authFrame')))

关于数据等待可以参考:如何等待页面元素加载完成》java实现,同时举了个需要页面等待的栗子。

(4)itunes登陆的代码示例

一切不上代码的演示都是耍流氓。

        import selenium,platform
        from selenium import webdriver
        from selenium.webdriver.common.by import By
        from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
        from selenium.common.exceptions import TimeoutException
        from selenium.webdriver.support.ui import WebDriverWait # available since 2.4.0
        from selenium.webdriver.support import expected_conditions as EC # available since 2.26.0
        from selenium.webdriver.common.by import By
        
        driverPath = '/home/phantomjs/bin/phantomjs'
        if platform.system()=='Windows':
            driverPath = 'D:/python_tool/phantomjs-2.0.0-windows/bin/phantomjs.exe'
#         driver = webdriver.PhantomJS(executable_path=driverPath) #使用phantomJs进行驱动
        driver = webdriver.Firefox() #使用FireFox进行模拟点击,运行此段代码的时候,会启动firefox
       
        url = 'https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa' # itunes登陆页面
        driver.get(url) # 跟浏览器一样加载页面
#        driver.implicitly_wait(10) #每次加载页面的时候等待10秒钟
        wait = WebDriverWait(driver, 30) # 页面加载时间可能比较长
        try: # 等待页面加载完成
            wait.until(EC.frame_to_be_available_and_switch_to_it((By.ID,'authFrame'))) # 等待出现id为authFrame的元素载入完成
            wait.until(EC.element_to_be_clickable((By.ID,'appleId'))) # 等待出现id为appId的元素可以点击
            print driver.title 
        except: 
            print 'error'*20
            driver.quit()
        # 输入账号、密码并点击提交
        driver.find_element_by_id('appleId').send_keys(self.account)
        driver.find_element_by_id('pwd').send_keys(self.password)
        driver.find_element_by_id('sign-in').click()
        # 显示等待一段页面跳转
        time.sleep(5)

        print '---  login success  ----'
        #print driver.get_cookies()#打印cookie
        for cookie in driver.get_cookies(): 
            print "%s -> %s" % (cookie['name'], cookie['value'])
        return
如果想访问别的数据页面,可以driver.get(url)和click方法逐步访问、点击。这个效率会比较低,selenium也可以使用多线程操作,但selenium并不保证多线程的数据一致性,简单的讲对多线程的支持不是很好。


四、混合模式

结合二、三两大步,通过模拟点击快速拿到cookie,虽然效率低,但可以减少数据包分析的时间以及解决搞不定ajax登陆验证的烦恼,然后继续用urllib2拼接cookie继续快速获取数据。分下面两步:

a. 从selenium中拿到cookie

b. 添加cookie给urllib2使用

方法1:使用CookieJar,可参考《Creating Custom Cookies for HTTP Requests

方法2:直接拼凑一个名称是"Cookie"的header。

五、全文总结

本文以python为编程语言介绍了爬虫登陆验证过程可以使用的两种方法:一个是数据包分析,另外一个是模拟点击。综合考虑开发效率,建议先用模拟点击的方法通过登陆验证,成功拿到cookie之后,拼凑一个Cookie-header,传递给urllib2进行常规调用。



版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

网络爬虫中的模拟登陆获取数据(实例教学)

目录模拟登陆的原因 如何模拟登陆 实战demo模拟登陆的原因很多网站,我们是无法直接获得服务器返回的数据,需要输入用户名及密码才能看到数据。如我们登陆人人网时,网站网址http://www.renre...

JAVA爬虫初识之模拟登录

JAVA爬虫模拟登录知乎

Java网络爬虫(二)--HttpClient设置头部信息(模拟登录)

在网络爬虫中我们经常需要设置一些头部信息,使我们进行网页抓取的行为更加像浏览器的行为,并且我们有时需要将头部信息设置正确,才能得到正确的数据,要不然有可能得到和浏览器所展示的页面有出入的信息。设置头部...

java网络爬虫[验证码模拟登陆]详细介绍

目录抓包介绍 解决验证码的思路 爬虫实战 爬虫架构 model main 解析htmlparse 数据库操作程序db 近期,有人将本人博客,复制下来,直接上传到百度文库等平台。 本文为原创博客,仅供...

[Python]网络爬虫(五):urllib2的使用细节与抓站技巧

前面说到了urllib2的简单入门,下面整理了一部分urllib2的使用细节。 1.Proxy 的设置 urllib2 默认会使用环境变量 http_proxy 来设置 HTTP Prox...

[Python]网络爬虫(三):异常的处理和HTTP状态码的分类

先来说一说HTTP的异常处理问题。 当urlopen不能够处理一个response时,产生urlError。 不过通常的Python APIs异常如ValueError,TypeError等也会同时产...

Python爬虫之自动登录与验证码识别

Python爬虫之自动登录与验证码识别在用爬虫爬取网站数据时,有些站点的一些关键数据的获取需要使用账号登录,这里可以使用requests发送登录请求,并用Session对象来自动处理相关Cookie。...

Python爬虫模拟真实登录案例系列之十二

模拟真实登录流程

[Python]网络爬虫(一):抓取网页的含义和URL基本构成

一、网络爬虫的定义 网络爬虫,即Web Spider,是一个很形象的名字。 把互联网比喻成一个蜘蛛网,那么Spider就是在网上爬来爬去的蜘蛛。 网络蜘蛛是通过网页的链接地址来寻找网页的。 从网站某一...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)