Robobrowser

提供者:郭铭昊

Robobrowser——一个轻量级爬虫库

常用于爬虫和简单的web测试,纯python编写,用起来很方便,语法自然,且易学。另外,robobrowser建立在requests和BeautifulSoup之上,容易被人们接受。官方介绍Robobrowser是:Your friendly neighborhood web scraper。

实现原理


要点

  • RoboState类里,页面上内容的抓取和处理实际上委托给了BeautifulSoup。RoboState类的_parsed对象实际上就是BeautifulSoup的实例;

  • RoboState类中保存了每个请求的响应内容——response.content;

  • RoboBrowser类里,发送请求的方法实际上委托给了requests类——session;

  • RoboBrowser类里比较复杂就是保存每次访问的状态,以及实现back和forward功能。其主要思想是把所有的访问历史都放在内存里,然后通过游标去访问;

  • 每次页面发生变化,也就是open和submit_form之后都会调用_update_state方法去更新当前状态;

  • 点击这里 了解详情.

流程梳理

  • RoboBrowser()实例化的时候,会new 1个requests的session用于发送http请求,同时初始化游标为-1并且当前的status列表初始化为空;

  • RoboBrowser.open(url)方法调用时,session对象会访问具体的url,然后更新游标和status列表。基本思想是往status列表里append 1个新new出来的RoboState对象;

  • RoboBrowser.find()方法调用时,使用当前游标处的state对象的_parsed对象的find方法去抓取页面内容,实际上就是BeautifulSoup的find方法;

安装Robobrowser


  • 使用pip安装:
          
    pip install robobrowser -i http://pypi.douban.com/simple/
    

小例子


  • 新建1个start.py文本文件,代码如下

          
          import re
          from robobrowser import RoboBrowser
    
          b = RoboBrowser(history=True)
          b.open('http://itest.info/courses/2')
    
          title = b.select('.headline h2')
          print title[0].text
    
          infos = b.select('h4')
    
          for info in infos:
              print info.text
    

文档查询


  • robobrowser自带文档shu说明,命令行运行:
            
          python -m pydoc -p 1234
    

简单的爬虫


代码讲解

        
        import re
        from robobrowser import RoboBrowser

        url = 'http://itest.info/courses/2'
        b = RoboBrowser(history=True)
        b.open(url)

        class_name = b.select('.headline h2')
        print class_name[0].text

        class_desc = b.select('.tag-box')
        print class_desc[0].text 

        class_time = b.select('h4')
        print class_time[0].text

        teacher = b.select('.thumbnail-style h3')
        print teacher[0].text

        qq = b.find(text=re.compile('QQ'))
        print qq

        qq_group = b.find(text=re.compile('\+selenium'))
        print qq_group
  • b = RoboBrowser(history=True) b.open(url) 用来创建browser和打开url;
  • b.select() 方法可以接受css选择器,返回页面上所有符合条件的元素的集合,也就是说返回的是list,可以进行迭代;
  • b.find(),只返回1个精确的结果;
  • 注意,find和select方法返回的均是Beautiful Soup的tag对象或对象集合;

抓取制定内容


背景

robobrowser支持Beautiful Soup,一般来说通过下面3个方法获取页面上感兴趣的内容

- find
- find_all
- select

find方法

find方法是返回页面上符合条件的第1个元素。


import re
from robobrowser import RoboBrowser
url = ‘http://itest.info/courses/2'
b = RoboBrowser(history=True)
b.open(url)

title = b.find('title')  
print title.text

img = b.find(id='logo-header')
print img['src']

print b.find(href='/courses/4').text

print b.find(class_='active', text=re.compile('python')).text

find_all方法

find_all方法的用法跟find基本相同,但是find_all会返回所有符合条件的tag的集合(ResultSet)。


import re
from robobrowser import RoboBrowser

url = 'http://itest.info/courses/2'
b = RoboBrowser(history=True)
b.open(url)

all_links = b.find_all('a')  
for link in all_links:
print link.text

divs = b.find_all(class_='container')
print divs

first_two_p = b.find_all('p', limit=2)
print first_two_p

print b.find_all(['meta', 'img'])

select方法

select方法支持css选择器,返回的是list。


import re
from robobrowser import RoboBrowser

url = 'http://itest.info/courses/2'
b = RoboBrowser(history=True)
b.open(url)

all_links = b.select('a')  
for link in all_links:
print link.text

divs = b.select('.container')
print len(divs)

其他技巧

  • 找到页面上所有具有id属性的元素 b.find_all(id=True)
  • 不递归查找元素。也就是说只在的直接子后代中查找 b.find(‘p’, recursive=False)

方法介绍

robobrowser的 follow_link 方法可以点击链接并自动完成跳转。


import re
from robobrowser import RoboBrowser
url = ‘http://www.qq.com/'
b = RoboBrowser(history=True)
b.open(url)

today_top = b.find(id='todaytop').a  
print today_top['href']
b.follow_link(today_top)

title = b.select('.hd h1')[0]
print '*************************************'
print title.text
print '*************************************'

print b.find(id='articleContent').text

  • follow_link的用法,一般来说都是用find/select/find_all方法过滤出相应的链接,然后调用b.follow_link(link)的方式去点击该链接。

表单操作


方法介绍

        
        import re
        from robobrowser import RoboBrowser

        url = 'http://testerhome.com/account/sign_in/'
        b = RoboBrowser(history=True)
        b.open(url)

        login_form = b.get_form(action='/account/sign_in')
        print login_form

        login_form['user[login]'].value = 'your account'
        login_form['user[password]'].value = 'your password'

        b.submit_form(login_form)
        print b.select('.alert.alert-success')[0].text
  • get_form 方法用来抓取form;
  • submit_form 方法用来提交表单;
  • form[name].value= 方法用来给文本框赋值,也就是说往文本框里写内容;

Beauiful Soup的过滤器


字符串

最简单的过滤器是字符串.在搜索方法中传入一个字符串参数,Beautiful Soup会查找与字符串完整匹配的内容,下面的例子用于查找文档中所有的b标签:


soup.find_all(‘b’)

正则表达式

如果传入正则表达式作为参数,Beautiful Soup会通过正则表达式的 match() 来匹配内容.下面例子中找出所有以b开头的标签,这表示 body 和 b 标签都应该被找到:


import re
for tag in soup.find_all(re.compile(“^b”)):
print(tag.name)

下面代码找出所有名字中包含”t”的标签:


for tag in soup.find_all(re.compile(“t”)):
print(tag.name)

列表

如果传入列表参数,Beautiful Soup会将与列表中任一元素匹配的内容返回.下面代码找到文档中所有 a 标签和 b 标签:


soup.find_all([“a”, “b”])

True

True 可以匹配任何值,下面代码查找到所有的tag,但是不会返回字符串节点


for tag in soup.find_all(True):
print(tag.name)

方法

如果没有合适过滤器,那么还可以定义一个方法,方法只接受一个元素参数 ,如果这个方法返回 True 表示当前元素匹配并且被找到,如果不是则反回 False

下面方法校验了当前元素,如果包含 class 属性却不包含 id 属性,那么将返回 True:


def has_class_but_no_id(tag):
return tag.has_attr(‘class’) and not tag.has_attr(‘id’)

将这个方法作为参数传入 find_all() 方法,将得到所有标签:


soup.find_all(has_class_but_no_id)

常用于爬虫和简单的web测试,纯python编写,用起来很方便。