美文网首页虫虫
网页信息提取

网页信息提取

作者: Cloud_J | 来源:发表于2019-01-29 16:04 被阅读42次

    Beautifulsoup库简介

    在介绍使用css选择器之前,我们先来了解一下要与其配合使用的Beautifulsoup库

    Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式.Beautiful Soup会帮你节省数小时甚至数天的工作时间.

    安装

    Beautifulsoup库的安装和requests库的安装类似,只要在命令行中用pip命令就可以了

    $ pip install beautifulsoup4
    

    Beautifulsoup库的使用

    还是以百度首页为例,我们先用requests库的get方法获得页面

    import requests
    # 从bs4库中导入Beautifulsoup类
    from bs4 import BeautifulSoup
    
    url = "http://www.baidu.com"
    r = requests.get(url)
    r.encoding = 'utf-8'
    # 用一个变量来保存爬到的页面
    html = r.text
    # 使用‘lxml HTML’作为解释器解析HTML
    soup = BeautifulSoup(html, 'lxml')
    # 格式化输出
    print(soup.prettify())
    
    # result
    # <html>
    #  <head>
    #   <meta content="text/html;charset=utf-8" http-equiv="content-type"/>
    #   <meta content="IE=Edge" http-equiv="X-UA-Compatible"/>
    #   <meta content="always" name="referrer"/>
    #   <link href="http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css" rel="stylesheet" type="text/css"/>
    #   <title>
    #    百度一下,你就知道
    #   </title>
    #  </head>
    #  <body link="#0000cc">
    #   <div id="wrapper">
    #    <div id="head">
    #     <div class="head_wrapper">
    # ... ...
    

    可以看到,用Beautifulsoup库解析之后的HTML被转换成了标签树,标签树的每一个节点都是一个python对象,因此我们就可以很方便地对标签树进行操作。

    CSS选择器

    CSS选择器是一种单独的文档搜索语法。Beautiful Soup支持大部分的CSS选择器,Tag和Beautifulsoup对象的.select()方法可以通过传入字符串参数找到对应的标签。

    例如我们要找title标签:

    title = soup.select("title")
    print(title)
    
    # [<title>百度一下,你就知道</title>]
    

    也可以通过标签逐层查找:

    title = soup.select('html head title')
    print(title)
    
    # [<title>百度一下,你就知道</title>]
    

    直接子标签查找:

    a = soup.select('p > a')
    print(a)
    
    '''
    [<a href="http://home.baidu.com">关于百度</a>,
     <a href="http://ir.baidu.com">About Baidu</a>,
     <a href="http://www.baidu.com/duty/">使用百度前必读</a>,
     <a class="cp-feedback" href="http://jianyi.baidu.com/">意见反馈</a>]
    '''
    

    通过类名和id查找:

    # 查找class='lb'的标签
    print(soup.select('.lb'))
    # 查找id='cp'的标签
    print(soup.select('#cp'))
    
    '''
    [<a class="lb" href="http://www.baidu.com/bdorz/login.gif?login&amp;tpl=mn&amp;u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1" name="tj_login">登录</a>]
    [<p id="cp">©2017 Baidu <a href="http://www.baidu.com/duty/">使用百度前必读</a>  <a class="cp-feedback" href="http://jianyi.baidu.com/">意见反馈</a> 京ICP证030173号  <img src="//www.baidu.com/img/gs.gif"/> </p>]
    '''
    

    除了以上的一些基本的查找方法外,还有组合查找、属性查找、语言设置查找等,可以参看官方文档中关于选择器的一节

    正则表达式

    正则表达式(Regular Expression)是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符")。

    正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。

    简单来说,正则表达式是用来简洁表达一组字符串的表达式。

    举个简单的例子,比如你要匹配字符串中的'PY''PYY''PYYYY'......'PYYYYYYYY...',它们对应的正则表达式就是'PY+'

    总的来说,正则表达式是

    • 通用的字符串表达框架
    • 简洁表达一组字符串的表达式
    • 针对字符串表达’简洁‘和’特征’思想的工具
    • 判断某字符串的特征归属

    正则表达式描述了一种字符串匹配的模式(pattern),可以用来检查一个串是否含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串等。

    正则表达式由字符操作符构成

    常用的操作符

    操作符 说明
    . 表示任何单个字符
    [] 字符集,对单个字符给出取值范围
    [^] 非字符集,对单个字符给出排除范围
    * 前一个字符的0次或无限次扩展
    + 前一个字符的1次或无限次扩展
    ? 前一个字符的0次或1次扩展
    | 左右表达式的任意一个
    {m} 扩展前一个字符m次
    {m,n} 扩展前一个字符m次到n次(包含)
    ^ 匹配字符串开始
    $ 匹配字符串结尾
    () 分组标记,内部只能使用|
    \d 数字,等价于[0-9]
    \w 单词字符,等价于[A-Zz-z0-9_]

    一些实例

    正则表达式 对应字符串
    P(Y|YT|YTH|YTHO)?N 'PN', 'PYN', 'PYTN', 'PYTHN', 'PYTHON'
    PYTHON+ 'PYTHON', 'PYTHONN',......,'PYTHONNN......'
    PYTH[ON] 'PYTHO', 'PYTHN'
    PYTH{1,3}ON 'PYTHON', 'PYTHHON', 'PYTHHHON'
    ^[A-Za-z]+$ 匹配由26个字母组成的字符串
    ^-?\d+$ 匹配整数字符串
    [1-9]\d{5} 中国境内邮政编码
    [\u4e00-\u9fa5] 匹配中文字符

    Re库

    re库是python中用于正则表达式匹配操作的标准库,不需要安装,可以直接通过import re导入

    re库采用的是原生字符串类型来表示正则表达式,原生字符串特点就是字符串中的‘\’不被解释为转义符,表示原生字符串只需要在字符串前面加上r就可以了

    re库的主要功能函数:

    函数 说明
    re.search() 在一个字符串中搜索匹配正则表达式的第一个位置,返回match对象
    re.match() 从一个字符串的开始位置起匹配正则表达式,返回match对象
    re.findall() 搜索字符串,以列表类型返回全部能匹配的子串
    re.split() 将一个字符串按照正则表达式匹配结果进行分割,返回列表类型
    re.finditer() 搜索字符串,返回一个匹配结果的迭代类型,每个迭代元素是match对象
    re.sub() 在一个字符串中替换所有匹配正则表达式的子串,返回替换后的字符串

    re.match(pattern, string, flags=0)

    ∙ pattern : 正则表达式的字符串或原生字符串表示

    ∙ string : 待匹配字符串

    ∙ flags : 正则表达式使用时的控制标记

    match()和search()的区别在于,match方法是从字符串的起始位置开始匹配,如果有一个字符不同便结束匹配,返回None;而search方法则是搜索整个字符串匹配符合规则的子串,以下是两种方法的比较

    import re
    
    re.search(r'b', 'abcba')  # <_sre.SRE_Match object; span=(1, 2), match='b'>
    re.match(r'b', 'abcba')   # no match
    re.search(r'a', 'abcba')  # <_sre.SRE_Match object; span=(0, 1), match='a'>
    re.match(r'a', 'abcba')   # <_sre.SRE_Match object; span=(0, 1), match='a'>
    

    如果匹配成功,返回的是一个match对象,其中包含很多信息

    match对象的属性和方法

    属性 说明 方法 说明
    .string 待匹配的文本 .group(0) 获得匹配后的字符串
    .re 匹配时使用的patter对象(正则表达式) .start() 匹配字符串在原始字符串的开始位置
    .pos 正则表达式搜索文本的开始位置 .end() 匹配字符串在原始字符串的结束位置
    .endpos 正则表达式搜索文本的结束位置 .span() 返回(.start(), .end())

    re.findall(pattern, string, flags=0)

    findall方法返回的是所有符合匹配规则的字符串组成的列表,顺序是根据字符串从左到右

    re.split(pattern, string, maxsplit=0, flags=0)

    根据pattern的出现拆分字符串。如果在pattern中使用捕获括号,则模式中所有组的文本也会作为结果列表的一部分返回。maxsplit表示最大分割数,如果maxsplit不为零,则至多出现maxsplit分裂,并且字符串的其余部分作为列表的最后一个元素返回。

    import re
    
    re.split(r'b', 'abcba')      # ['a', 'c', 'a']
    re.split(r'(b)', 'abcba')    # ['a', 'b', 'c', 'b', 'a']
    re.split(r'b', 'abcba', 1)   # ['a', 'cba']
    re.split(r'(b)', 'abcba', 1) # ['a', 'b', 'cba']
    

    re.finditer(pattern, string, flags=0)

    与findall方法作用相同,只不过是以迭代器的形式返回

    re.sub(pattern, repl, string, count=0, flags=0)

    · repl:替换匹配字符串的字符串

    ∙ count : 匹配的最大替换次数,为0时替换全部

    string中最左侧非重叠出现的pattern替换为repl,返回所获得的字符串。如果未找到该模式,则字符串将保持不变。repl 可以是一个字符串或一个函数

    import re
    
    re.sub(r'b','d','abcba')    # 'adcda'
    re.sub(r'b','d','abcba', 1) # 'adcba'
    

    flags

    可以看到之前所以的函数中都有一个参数flags,它是用来配置正则表达式的匹配模式的。

    取值可以使用按位或运算符|表示同时生效,比如re.I | re.M。(来自静觅)

    • re.I(全拼:IGNORECASE): 忽略大小写(括号内是完整写法,下同)
    • re.M(全拼:MULTILINE): 多行模式,改变’^’和’$’的行为
    • re.S(全拼:DOTALL): 点任意匹配模式,改变’.’的行为
    • re.L(全拼:LOCALE): 使预定字符类 \w \W \b \B \s \S 取决于当前区域设定
    • re.U(全拼:UNICODE): 使预定字符类 \w \W \b \B \s \S \d \D 取决于unicode定义的字符属性
    • re.X(全拼:VERBOSE): 详细模式。这个模式下正则表达式可以是多行,忽略空白字符,并可以加入注释。

    Chrome开发者工具

    如何调出Chrome开发者工具

    • 按F12打开
    • 单击右键,在菜单中点击“检查”打开

    常用面板模块

    • 元素(Elements)
    • 网络(Network)

    这里只介绍在写爬虫时可能会用到的两个功能模块,如果想了解其他的可以在网上找详细的教程

    元素(Element)

    单击Element标签页,页面左边显示的是HTML的结构,右边是选中元素的全部属性

    • 鼠标移到某个元素上,页面视图上对应的地方会变成蓝色背景,可以用于定位元素对应的源代码。
    • 选中一个元素,在底部可以看到该元素在HTML结构中的位置关系
    • 右键一个元素可以对其进行修改,菜单从上到下依次是
      • Add attribute : 为该元素添加属性
      • Edit attribute:修改该元素的属性
      • Delete element:删除元素
      • Copy:复制元素的一些信息,移到上面会显示二级菜单
      • ... ...
    • 写某个元素的CSS选择器的时候,可以右键该元素,copy selector(有些版本叫CSS path或者CSS selector)

    右侧显示的是选中元素的CSS属性,在Styles可以对CSS属性进行修改,删除和添加,仅对当前显示的页面生效,不会影响到源代码。

    网络(Network)

    Network是一个监控当前网页所有的http请求的面版,它主体部分展示的是每个http请求,每个字段表示着该请求的不同属性和状态

    • name:请求的文件名称
    • status:状态代码
    • type:文件类型
    • initiator:请求源
    • time:请求的时间
    • waterfall:请求发送过程的状态轴

    当你按F5刷新页面的时候,可以看到最中间的的时间轴上花花绿绿的一条条线显示出来。这个记录的是页面在加载过程中所有的请求发出的时间和过程,你可以用鼠标选择一段时间,来观察这一段时间发出的请求内容

    单击Name一列任意一个请求的文件名,则会跳出这个请求对应的参数header(表头信息、返回信息、请求基本状态等),Preview(返回的格式化转移后文本信息)、response(转移之前的原始信息)、Cookies(该请求带的cookies)、Timing(请求时间变化)。这些东西可以用来分析请求,在讲反爬虫的时候我们会深入介绍。


    参考资料:
    Beautifulsoup库官方文档
    re库官方文档

    相关文章

      网友评论

        本文标题:网页信息提取

        本文链接:https://www.haomeiwen.com/subject/cavxsqtx.html