网页信息提取

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
# 
#  
#   
#   
#   
#   
#   
#    百度一下,你就知道
#   
#  
#  
#   
#

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

CSS选择器

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

例如我们要找title标签:

title = soup.select("title")
print(title)

# [百度一下,你就知道]

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

title = soup.select('html head title')
print(title)

# [百度一下,你就知道]

直接子标签查找:

a = soup.select('p > a')
print(a)

'''
[关于百度,
 About Baidu,
 使用百度前必读,
 意见反馈]
'''

通过类名和id查找:

# 查找class='lb'的标签
print(soup.select('.lb'))
# 查找id='cp'的标签
print(soup.select('#cp'))

'''
[登录]
[

©2017 Baidu 使用百度前必读 意见反馈 京ICP证030173号

] '''

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

正则表达式

正则表达式(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库官方文档

你可能感兴趣的:(网页信息提取)