关于Python的爬虫的一些数据提取的方法总结

  • 第一种 : 正则表达式
  • 2. 正则表达式相关注解
  • 2.1 数量词的贪婪模式与非贪婪模式
  • 2.2 常用方法
  • 第二种:bs4 的使用
  • 第三种 : Xpath
  • 第四种 : jsonPath
  • 3.1 json.loads()
  • 3.2 json.dumps()
  • 3.3 json.dump()
  • 使用这个的好处


第一种 : 正则表达式

  1. 正则表达式是 对于it来说最常用的一个,就是用事先定义好的一些特定的字符,及这些特定的组合,组成一个"规则字符串",
  2. 规则

模式

描述

^

匹配字符串的开头

$

匹配字符串的末尾

.

匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符

[…]

用来表示一组字符,单独列出:[amk] 匹配 ‘a’,‘m’或’k’

[^…]

不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符

re*

匹配0个或多个的表达式

re+

匹配1个或多个的表达式

re?

匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式

re{ n}

re{ n,}

精确匹配n个前面表达式

re{ n, m}

匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式

a

b

(re)

G匹配括号内的表达式,也表示一个组

(?imx)

正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域

(?-imx)

正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域

(?: re)

类似 (…), 但是不表示一个组

(?imx: re)

在括号中使用i, m, 或 x 可选标志

(?-imx: re)

在括号中不使用i, m, 或 x 可选标志

(?#…)

注释

(?= re)

前向肯定界定符。如果所含正则表达式,以 … 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。

(?! re)

前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功

(?> re)

匹配的独立模式,省去回溯

\w

匹配字母数字及下划线

\W

匹配非字母数字及下划线

\s

匹配任意空白字符,等价于 [\t\n\r\f].

\S

匹配任意非空字符

\d

匹配任意数字,等价于 [0-9]

\D

匹配任意非数字

\A

匹配字符串开始

\Z

匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。c

\z

匹配字符串结束

\G

匹配最后匹配完成的位置

\b

匹配一个单词边界,也就是指单词和空格间的位置。例如, ‘er\b’ 可以匹配"never" 中的 ‘er’,但不能匹配 “verb” 中的 ‘er’

\B

匹配非单词边界。‘er\B’ 能匹配 “verb” 中的 ‘er’,但不能匹配 “never” 中的 ‘er’

\n, \t, 等.

匹配一个换行符。匹配一个制表符。等

\1…\9

匹配第n个分组的内容

\10

匹配第n个分组的内容,如果它经匹配。否则指的是八进制字符码的表达式

[\u4e00-\u9fa5]

中文

2. 正则表达式相关注解

2.1 数量词的贪婪模式与非贪婪模式

正则表达式通常用于在文本中查找匹配的字符串
Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符;非贪婪的则相反,总是尝试匹配尽可能少的字符

例如:正则表达式”ab*”如果用于查找”abbbc”,将找到”abbb”。而如果使用非贪婪的数量词”ab*?”,将找到”a”

2.2 常用方法

  • re.match
  • re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none
  • 函数语法:
    re.match(pattern, string, flags=0)
  • re.search
  • re.search 扫描整个字符串并返回第一个成功的匹配。
  • 函数语法:
    re.search(pattern, string, flags=0)
  • re.sub
  • re.sub 替换字符串
    re.sub(pattern,replace,string)
  • re.findall
  • re.findall 查找全部
    re.findall(pattern,string,flags=0)

第二种:bs4 的使用

  1. bs4 就是Beautiful Soup 的简称,这是一个工具箱,通过解析文档为用户提供需要抓取的数据,
  2. 使用这个不需要在编码的上面考虑,他会自动转换为utf-8编码。
  3. 但是使用这个的前提的就是网页是完整的,但是现在的网页大多规范化,所以都是可以用的
  4. 官网: http://beautifulsoup.readthedocs.io/zh_CN/latest/
  5. bs4 必须使用一种解析器,如果你没有安装其他的HTML解析器,他会默认使用自带的解析器,但是lxml 解析器更加强大,速度更快,推荐安装
  6. 对于 四种解析器的对比

解析器

使用方法

优势

劣势

Python标准库

BeautifulSoup(markup, “html.parser”)

1. Python的内置标准库 2. 执行速度适中 3.文档容错能力强

Python 2.7.3 or 3.2.2)前 的版本中文档容错能力差

lxml HTML 解析器

BeautifulSoup(markup, “lxml”)

1. 速度快 2.文档容错能力强

需要安装C语言库

lxml XML 解析器

BeautifulSoup(markup, [“lxml”, “xml”]) BeautifulSoup(markup, “xml”)

1. 速度快 2.唯一支持XML的解析器 3.需要安装C语言库

html5lib

BeautifulSoup(markup, “html5lib”)

1. 最好的容错性 2.以浏览器的方式解析文档 3.生成HTML5格式的文档 4.速度慢

不依赖外部扩展

  1. 对于bs4 有四大对象种类
  1. Tag
  2. navigableString
  3. BeautifulSoup
  4. Comment
  1. 更加细致的编写的方法,可以去官网查看

第三种 : Xpath

  1. 相对于其他的方法,我更加的喜欢这种方法,因为更加的方便
  2. 官网 : http://lxml.de/index.html
  3. w3c :http://www.w3school.com.cn/xpath/index.asp
  4. xpath 是一门在XML文档中查找信息的语言,
  5. 是以节点来表达关系的
  • 父(Parent)
  • 子(Children)
  • 同胞(Sibling)
  • 先辈(Ancestor)
  • 后代(Descendant)
  1. 选取节点
  1. 常用的路径表达式

表达式

描述

nodename

选取此节点的所有子节点

/

从根节点选取

//

从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置

.

选取当前节点


选取当前节点的父节点

@

选取属性

  1. 通配符

XPath 通配符可用来选取未知的 XML 元素。

通配符

描述

举例

结果

*

匹配任何元素节点

xpath(‘div/*’)

获取div下的所有子节点

@*

匹配任何属性节点

xpath(‘div[@*]’)

选取所有带属性的div节点

node()

匹配任何类型的节点

  1. 选取若干路径

通过在路径表达式中使用“|”运算符,您可以选取若干个路径

表达式

结果

xpath(’//div|//table’)

获取所有的div与table节点

  1. 谓语

谓语被嵌在方括号内,用来查找某个特定的节点或包含某个制定的值的节点

表达式

结果

xpath(’/body/div[1]’)

选取body下的第一个div节点

xpath(’/body/div[last()]’)

选取body下最后一个div节点

xpath(’/body/div[last()-1]’)

选取body下倒数第二个节点

xpath(’/body/div[positon()< 3]’)

选取body下前个div节点

xpath(’/body/div[@class]’)

选取body下带有class属性的div节点

xpath(’/body/div[@class=“main”]’)

选取body下class属性为main的div节点

xpath(’/body/div[price>35.00]’)

选取body下price元素大于35的div节点

第四种 : jsonPath

这个是Python自带的轻量级的数据交换格式,这个与XML相较比不相上下

3.1 json.loads()

  1. Python中的json 模块
    - 提供了四个功能 : dumps,dump,loads,load 用于字符串和Python数据类型进行转换

把Json格式字符串解码转换成Python对象 从json到python的类型转化对照如下:

import json

strList = '[1, 2, 3, 4]'
strDict = '{"city": "北京", "name": "范爷"}'
json.loads(strList) 
# [1, 2, 3, 4]
json.loads(strDict) # json数据自动按Unicode存储
# {u'city': u'\u5317\u4eac', u'name': u'\u5927\u732b'}

3.2 json.dumps()

实现python类型转化为json字符串,返回一个str对象 把一个Python对象编码转换成Json字符串

从python原始类型向json类型的转化对照如下:

# json_dumps.py

import json


listStr = [1, 2, 3, 4]
tupleStr = (1, 2, 3, 4)
dictStr = {"city": "北京", "name": "范爷"}

json.dumps(listStr)
# '[1, 2, 3, 4]'
json.dumps(tupleStr)
# '[1, 2, 3, 4]'

# 注意:json.dumps() 序列化时默认使用的ascii编码
# 添加参数 ensure_ascii=False 禁用ascii编码,按utf-8编码

json.dumps(dictStr) 
# '{"city": "\\u5317\\u4eac", "name": "\\u5927\\u5218"}'

print(json.dumps(dictStr, ensure_ascii=False))
# {"city": "北京", "name": "范爷"}

3.3 json.dump()

将Python内置类型序列化为json对象后写入文件

import json

listStr = [{"city": "北京"}, {"name": "范爷"}]
json.dump(listStr, open("listStr.json","w"), ensure_ascii=False)

dictStr = {"city": "北京", "name": "范爷"}
json.dump(dictStr, open("dictStr.json","w"), ensure_ascii=False)

使用这个的好处

  1. 如果网页是用ajax来进行 数据交互的,
  2. 使用jsonPath 就是可以直接使用url 来进行获取数据,相对于其他就更加的方便
  3. 示例
from urllib.request import urlopen
from urllib.request import Request
import jsonpath
import json


url = 'http://www.lagou.com/lbs/getAllCitySearchLabels.json'
request =Request(url)
response = urlopen(request)
html = response.read()
# 把json格式字符串转换成python对象
jsonobj = json.loads(html)
# 从根节点开始,匹配name节点
citylist = jsonpath.jsonpath(jsonobj,'$..name')
print(citylist)
print(type(citylist))
fp = open('city.json','w')
content = json.dumps(citylist, ensure_ascii=False)
print(content)
fp.write(content)
fp.close()