Python爬虫入门——数据提取与清晰策略

Python爬虫入门——数据提取与清晰策略

正则表达式

表达式 说明
. 除了\n和\r的所有字符
\d 数字
\D 非数字
\w 数字字母和下划线
\W 非数字字母和下划线
\s 空格(包括制表符、换页符)
------------------------------- -------------------------------------
[a-z] 小写应为字母
[a-zA-Z0-9] 大小写英文字母与数字
[123] 数字123
[^ 123] 不是数字123
* 出现次数>=0
+ 出现次数>=1
{n} 出现次数=n
{n,m} m>=出现次数>=n
^ 以开头
$ 以结尾
关闭贪婪模式
() 用于获取括号内匹配成功的字符串
  1. 案例

定义密码的正则表达式:
规则:英文字母开头,可以包括数字、大小写英文字母、下划线,6-16位

password_pattern = '^ [a-zA-Z]{1}[a-zA-Z0-9_]{5-15}$'
#等价于
password_pattern = '^ [a-zA-Z][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><div class='class1'>**要匹配的内容</div>**</div> #正则表达式默认开启贪婪模式,默认匹配尽可能多的字符串 #取消贪婪模式: div_pattern = '
(.*?)
'
#匹配结果为: <div><div class='class1'>**要匹配的内容**</div></div>

re模块使用案例

  1. 提取
  2. 匹配
  3. 替换
提取
#导入re模块
import re
#findall方法
ret = re.findall(【正则表达式】,【被提取的字符串】)
#注:返回的类型是列表,如果未匹配成功返回一个空列表
匹配
import re
#match方法
ret = re.match(【正则表达式】,【被匹配的字符串】)
#注:匹配密码
#    如果匹配成功,返回对象
#    如果匹配不成功,返回None
替换
import re
# sub方法
ret = re.sub(【正则表达式】,【替换成的字符串】,【被替换的字符串】)
三种方法的使用
import re

with open('index.html','r',encoding='utf-8') as f:
    html = f.read()
    #替换文件中换行符
    html = re.sub('\n','',html)
    print(html)
    #提取数据
    pattern_1 =''
    ret_1 = re.findall(pattern_1,html)
    #去掉空格
    print(ret_1[0].strip())
#匹配密码
password_pattern = r'^[a-zA-Z][a-zA-Z0-9_]{5,15}$'
pass1 = '1234567'
pass2 = 'k123456'
pass3 = 'k123'
print(re.match(password_pattern,pass1))
print(re.match(password_pattern,pass2))
print(re.match(password_pattern,pass3))

提取商城分类结构

对下面HTML文件进行提取

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>CSDN微课商城</title>
    <link rel="stylesheet" href="../css/main.css">
    <script type="text/javascript" src="../js/main.js"></script>
</head>
<body>

<div id="register" hidden="hidden">
    <h2 class="form_p">注册</h2>
    <p id="register_message">
        <!--信息有误-->
    </p>
    <form action="#" method="post" id="register_form">
        <input id="register_account" type="text" name="account" placeholder="账号(数字、英文、下换线,8-16位)"><br/>
        <input id="register_password" type="password" name="password" placeholder="密码(数字、英文、下换线,6-16位)"><br/>
        <!--<input type="password" name="repassword" placeholder="确认密码"><br/>-->
        <input id="register_submit" type="submit" value="注册">
    </form>
</div>

<div id="login" hidden="hidden">
    <h2 class="form_p">登录</h2>
    <p id="login_message">
        <!--信息有误-->
    </p>
    <form action="#" method="post" id="login_form">
        <input id="login_account" type="text" name="account" placeholder="账号"><br>
        <input id="login_password" type="password" name="password" placeholder="密码"><br>
        <input id="login_submit" type="submit" value="登录">
    </form>
</div>

<header>
    <span class="title"> <a href="index.html">CSDN微课商城</a> </span>
    <span>
        <form action="#" class="search_form">
            <input type="text" name="course" placeholder="按课程名称搜索">
            <input type="submit" value="搜索">
        </form>
    </span>
    <span class="user">
        <a href="javascript:show('login')">登录</a>/
        <a href="javascript:show('register')">注册</a>
        <!-- 已经登录显示的内容 -->
        你好:
        <a href="user.html">用户1</a>
        <a href="#">注销</a>
    </span>
</header>

<article>
    <section class="nav_section"><img src="../img/csdn_static/2.png" alt="" width="100%"></section>
    <section class="main_section"><h1>第一章 路由与模板</h1>
        <figure><a href="course.html"> <img src="../img/course/course.png">
            <figcaption><span class="course_name">Web原理与框架简介</span><span class="price">75</span></figcaption>
        </a></figure>
        <figure><a href="course.html"> <img src="../img/course/course.png">
            <figcaption><span class="course_name">Django环境搭建与入门案例</span><span class="price">153</span></figcaption>
        </a></figure>
        <figure><a href="course.html"> <img src="../img/course/course.png">
            <figcaption><span class="course_name">基本路由映射与命名空间</span><span class="price">154</span></figcaption>
        </a></figure>
        <figure><a href="course.html"> <img src="../img/course/course.png">
            <figcaption><span class="course_name">正则路由映射参数的传递与接收</span><span class="price">177</span></figcaption>
        </a></figure>
        <figure><a href="course.html"> <img src="../img/course/course.png">
            <figcaption><span class="course_name">反向解析处理器</span><span class="price">161</span></figcaption>
        </a></figure>
        <figure><a href="course.html"> <img src="../img/course/course.png">
            <figcaption><span class="course_name">Request对象与Response对象</span><span class="price">44</span></figcaption>
        </a></figure>
        <figure><a href="course.html"> <img src="../img/course/course.png">
            <figcaption><span class="course_name">上下文与模板调用</span><span class="price">97</span></figcaption>
        </a></figure>
        <figure><a href="course.html"> <img src="../img/course/course.png">
            <figcaption><span class="course_name">模板层基础语法</span><span class="price">105</span></figcaption>
        </a></figure>
        <figure><a href="course.html"> <img src="../img/course/course.png">
            <figcaption><span class="course_name">模板过滤器</span><span class="price">133</span></figcaption>
        </a></figure>
    </section>
    <section class="main_section"><h1>第二章 模型类实现</h1>
        <figure><a href="course.html"> <img src="../img/course/course.png">
            <figcaption><span class="course_name">ORM原理与数据库配置</span><span class="price">143</span></figcaption>
        </a></figure>
        <figure><a href="course.html"> <img src="../img/course/course.png">
            <figcaption><span class="course_name">表与字段的定义和常用字段约束</span><span class="price">118</span></figcaption>
        </a></figure>
        <figure><a href="course.html"> <img src="../img/course/course.png">
            <figcaption><span class="course_name">数据迁移与维护</span><span class="price">57</span></figcaption>
        </a></figure>
        <figure><a href="course.html"> <img src="../img/course/course.png">
            <figcaption><span class="course_name">模型类的增删改</span><span class="price">45</span></figcaption>
        </a></figure>
        <figure><a href="course.html"> <img src="../img/course/course.png">
            <figcaption><span class="course_name">模型类的查询方法</span><span class="price">187</span></figcaption>
        </a></figure>
        <figure><a href="course.html"> <img src="../img/course/course.png">
            <figcaption><span class="course_name">QuerySet详解</span><span class="price">197</span></figcaption>
        </a></figure>
    </section>
</article>

<footer>
    <div id="footer_div1">
        <p><a href="#">关于我们</a>| <a href="#">招聘</a>| <a href="#">广告服务</a>| <a href="#">网站地图</a></p>
        <p><a href="#">QQ客服</a>| <a href="#">kefu@csdn.ent</a>| <a href="#">客服论坛</a>| <a href="#">400-660-0108</a>| <a
                href="#">工作时间:8:30-22:00</a></p>
        <p> 百度提供站内搜索 北ICP备19004658 </p>
        <p> ©1999-2019 北京创新乐知网络技术有限公司 </p>
        <p> 版权申诉 家长监护 经营性网站备案信息 网络110报警服务 中国互联网举报中心 北京互联网违法和不良信息举报中心 </p>
    </div>
    <div id="footer_div2">
        <figure><img src="../img/csdn_static/二维码1.png">
            <figcaption>CSDN咨询</figcaption>
        </figure>
        <figure><img src="../img/csdn_static/二维码1.png">
            <figcaption>CSDN学院</figcaption>
        </figure>
        <figure><img src="../img/csdn_static/二维码1.png">
            <figcaption>CSDN企业招聘</figcaption>
        </figure>
    </div>
</footer>

</body>
</html>

提取过程

import re

with open('static/html/index.html','r',encoding='utf-8') as f:
    #去掉换行符
    html =re.sub('\n','',f.read())
    #print(html)
    #提取课程种类
    #建立正则表达式
    section_pattern = '
(.*?)
'
section_s = re.findall(section_pattern,html) print(section_s) print(len(section_s)) #建立课程种类的正则表达式 category_pattern = '

(.*?)

'
#建立课程名称的正则表达式 course_pattern ='(.*?)' #建立一个列表 data_s=[] #遍历section_s for section in section_s: #在section中取到课程种类对象 category = re.findall(category_pattern,section) #取到课程种类对象列表中的课程种类信息 #print(category[0]) course_s = re.findall(course_pattern,section) data_s.append( { 'category':category, 'course_s':course_s } ) print(data_s) for data in data_s: print(data.get('category')) for course in course_s: print(' ',course)

提取结果

C:\Users\Lenovo\AppData\Local\Programs\Python\Python38\python.exe C:/Users/Lenovo/PycharmProjects/提取商城分类结构/re_index.py
['

第一章 路由与模板

Web原理与框架简介¥75
Django环境搭建与入门案例¥153
基本路由映射与命名空间¥154
正则路由映射参数的传递与接收¥177
反向解析处理器¥161
Request对象与Response对象¥44
上下文与模板调用¥97
模板层基础语法¥105
模板过滤器¥133
'
, '

第二章 模型类实现

ORM原理与数据库配置¥143
表与字段的定义和常用字段约束¥118
数据迁移与维护¥57
模型类的增删改¥45
模型类的查询方法¥187
QuerySet详解¥197
'
] 2 [{'category': ['第一章 路由与模板'], 'course_s': ['Web原理与框架简介', 'Django环境搭建与入门案例', '基本路由映射与命名空间', '正则路由映射参数的传递与接收', '反向解析处理器', 'Request对象与Response对象', '上下文与模板调用', '模板层基础语法', '模板过滤器']}, {'category': ['第二章 模型类实现'], 'course_s': ['ORM原理与数据库配置', '表与字段的定义和常用字段约束', '数据迁移与维护', '模型类的增删改', '模型类的查询方法', 'QuerySet详解']}] ['第一章 路由与模板'] ORM原理与数据库配置 表与字段的定义和常用字段约束 数据迁移与维护 模型类的增删改 模型类的查询方法 QuerySet详解 ['第二章 模型类实现'] ORM原理与数据库配置 表与字段的定义和常用字段约束 数据迁移与维护 模型类的增删改 模型类的查询方法 QuerySet详解

XPath语法与案例

  1. 谷歌浏览器(任意)配置XPath插件
  2. XPath常用语法
  3. XPath应用案例
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()

Python中的lxml模块

实战数据提取CSND学院主页数据

截取操作代码

import lxml.etree as le

with open('edu.html','r',encoding='utf-8') as f:
    html = f.read()
    html_x = le.HTML(html)
    #print(html_x)
    div_x_s = html_x.xpath('//div[@class="classify_cList"]')
    #print(div_x_s)
    data_s = []
    for div_x in div_x_s:
        category1=div_x.xpath('./h3/a/text()')[0]
        #print(category1)
        category2_s = div_x.xpath('./div/span/a/text()')
        #print(category2_s)
        data_s.append(
            dict(
                category1=category1,
                category2_s=category2_s
                )
        )
        #print(data_s)
        for data in data_s:
            print(data.get('category1'))
            for category2 in data.get('category2_s'):
                print('    ',category2)

百度针对XPath 爬虫的反扒策略与解决方式

读取正常百度数据
import lxml.etree as le
with open('meiju1.html','r',encoding='utf-8') as f:
    html = f.read()
    html_x = le.HTML(html)
    title_s = html_x.xpath('//div[contains(@class,"threadlist_title pull_left j_th_tit")]/a/text()')
    print(title_s)
    for title in title_s:
        print(title)
读取被注释掉的百度数据
import lxml.etree as le
import re
with open('meiju2.html','r',encoding='utf-8') as f:
    html = re.sub('\n','',f.read())
    title_pattern = '
.*?(.*?)' title_s = re.findall(title_pattern,html) for title in title_s: print(title)

JsonPath使用案例

dumps和loads用法

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))
#loads 用于把Json对象转换成Python对象
python_data2 = json.loads(json_data)
print(python_data2)
print(type(python_data2))

dump和load用法

import json

python_data = [
    {
        'username':'name1',
        'vip':True
    },
    {
        'username':None,
        'vip':False,
    }
]

#dump 用于把Python类型的数据转换成Json类型的字符串,保存到本地
json.dump(python_data,open('json.txt','w'))
#load 用于读取本地json数据本转换成python对象
python_data2=json.load(open('json.txt'))
print(python_data2)

你可能感兴趣的:(python)