数据提取和清洗策略
正则表达式
正则表达式常用命令
常用命令 | 含义 |
---|---|
. | 除了\n\r的所有字符 |
\d | 数字 |
\D | 非数字 |
\w =[a-zA-Z0-9_] | 数字、字母、下划线 |
\W | 非数字字母和下划线 |
\s | 空格(包括制表符换页符) |
[a-z] | 小写英文字母 |
[a-zA-Z0-9] | 大小写英文字母和数字 |
[123] | 数字123 |
[^123] | 不是数字123 |
* | 出现次数>=0 |
+ | 出现次数>=1 |
{n} | 出现次数=n |
{n,m} | n<=出现次数<=m |
^ | 以开头 |
$ | 以结尾 |
? | 关闭贪婪模式 |
‘()’ | 用于获取括号内匹配成功的字符串 |
正则表达式案例
-
定义密码的正则表达式:英文字母开头,可以包括数字、大小写英文字母、下划线,6-16位
password_pattern = ‘^ [a-zA-Z]{1}[a-zA-Z0-9_]{5-15} $’
-
匹配div标签,class=“class1”中的文本内容:<div class = “class1”> 要匹配的内容</div>
div_pattern = '<div class = "class1">(.*)</div>'
-
匹配div标签,class=“class1”中的文本内容:<div><div class = “class1”> 要匹配的内容</div></div>
div_pattern = '<div class = "class1">(.*)</div>' # 如果还是这么写的话,那么匹配到的将会是 # 要匹配的内容</div> # 多了一个div标签是因为正则表达式正常是贪婪模式,会尽可能匹配多的内容 # 因此我们需要关闭贪婪模式 div_pattern = '<div class = "class1">(.*?)</div>'
re模块
re模块常用命令
命令 | 含义 |
---|---|
*search(···) | 在整个字符串中查找,返回第一个匹配的内容,如果找到返回match对象,如果没有返回None |
*match(【正则表达式】,【被提取的字符串】) | 从头匹配,如果找到返回match对象,如果没有返回None |
*findall(【正则表达式】,【被提取的字符串】) | 找到所有符合的,返回列表类型 |
finditer(···) | 在字符串中匹配 |
split(···) | 按照匹配的字符串分割 |
*sub(【正则】,【替换成的字符串】,【被匹配的字符串】) | 替换匹配的子字符串,返回替换后的字符串 |
group() | 结果转化为内容 |
groupdict() | 结果转化为字典 |
<body>
<footer>
<div>
<div class="email">
Email:kkk@qq.com
</div>
<div class="tel">
手机号:400-4000-6666
</div>
</div>
</footer>
</body>
import re
with open('index.html','r',encoding='utf-8')as f:
html = f.read()
print(html)
# 2.将所有换行符替换成''
html = re.sub('\n','',html)
print(html)
pattern_1 = '<div class="email">(.*?)</div>'
ret_1 = re.findall(pattern_1,html)
print(ret_1[0].strip())# 3. 消除首位空格和换行符
# 返回结果是空列表,因为没有对\n换行符进行过滤
import re
with open('static/html/index.html','r',encoding='utf-8') as f:
html = f.read()
html = re.sub('\n', '', html)
#print(html)
section_pattern = '<section class="main_section">(.*?)</section>'
# 将含有课程种类和课程名称的一大块提取出来
section_s = re.findall(section_pattern,html)
# print(section_s)
# print(len(section_s))
category_pattern = '<h1>(.*?)</h1>'
# 课程种类的正则表达式
course_pattern = '<span class="course_name">(.*?)</span>'
# 课程名称的正则表达式
data_s = []
for section in section_s:
category = re.findall(category_pattern,section)[0]
course = re.findall(course_pattern,section)
data_s.append(
{
'category':category,
'course':course
}
)
print(data_s)
for data in data_s:
print(data.get('category'))
for course in data.get('course'):
print(' ',course)
XPath
XPath即为XML路径语言,它是一种用来确定XML文档中某部分位置的语言
谷歌浏览器配置XPath插件
- 点击拓展程序
- 拖拽xpath—helper.crx到浏览器
- 出现安装包无效的问题:
1、将crx结尾的扩展包的后缀名更改为rar格式的压缩包文件,直接确认
2、将压缩包进行解压缩,然后将路径下的_metadata改为metadata
3、进入Chrome浏览器的加载扩展程序界面,点击“加载已解压的扩展程序”,进入解压后的文件夹就可以直接安装了。
XPath常用语法
表达式 | 描述 |
---|---|
/ | 根节点选取或下级 |
// | 任意节点,不考虑位置 |
. | 当前节点 |
… | 当前节点的父节点 |
@ | 选取属性 |
* | 匹配任何节点 |
[nodename] | 根据节点筛选 |
contains(@属性,“包含的内容”) | 模糊查询 |
text() | 文本内容 |
注意:XPath中的索引从1开始
应用案例
//h3[@class='classify_c_h3']/a/text()
//div[@class='classify_list']/span/a/text()
//div[contains(@class,'classify_list')]/span/a/text()
在pycharm中引入lxml.etree 包标红解决办法:在file-setting-project-project interpreter 中点击右方加号install lxml
百度针对XPath爬虫的反爬策略和解决方式
反爬策略:将html代码注释,再在js中取消注释来反lxml爬虫,则用正则表达式进行爬取
import lxml.etree as le
with open('meiju1.html','r',encoding='utf-8') as f:
# meiju2 有反爬,需要用正则表达式
html = f.read()
html_x = le.HTML(html)
print(html_x)
title_s = html_x.xpath('//div[contains(@class,"threadlist_title pull_left j_th_tit")]/a/text()')
for title in title_s:
print(title)
import re
with open('meiju2.html','r',encoding='utf-8') as f:
html = f.read()
html = re.sub('\n','',html)
title_pattern = '<div class="threadlist_title pull_left j_th_tit ">.*?<a.*?>(.*?)</a>'
title_s = re.findall(title_pattern,html)
for title in title_s:
print(title)
JsonPath使用案例
import json
python_data = [
{
'username':'name1',
'vip':True
},
{
'username':None,
'vip':False
}
]
# dumps 用于把python对象转换成json对象
json_data = json.dumps(python_data)
print(json_data)
print(type(json_data))# str
# loads 用于把json对象转化成python对象
python_data2 = json.loads(json_data)
print(python_data2)
print(type(python_data2))# list
# dump 把python类型的数据转化成json类型的字符串,然后保存到本地
json.dump(python_data,open('json.txt','w'))
# load 用于读取本地的json数据,并转换成python对象
python_data3 = json.load(open('json.txt'))
print(python_data3)
print(type(python_data3))#list