网页信息提取

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库官方文档

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,458评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,454评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,171评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,062评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,440评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,661评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,906评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,609评论 0 200
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,379评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,600评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,085评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,409评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,072评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,088评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,860评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,704评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,608评论 2 270

推荐阅读更多精彩内容