一、方式一:正则表达式

要掌握正则表达式的常用符号,包括

  • 一般字符

. 匹配任意单个字符

转义字符

[...]字符集

  • 预定义字符集

d 匹配一个数字字符。等价于 [0-9]。

D 匹配一个非数字字符。等价于 [^0-9]。

s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ fnrtv]

S 匹配任何非空白字符。等价于 [^ fnrtv]

w 匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]

W 匹配任何非单词字符。等价于 '[^A-Za-z0-9_]

  • 数量词

* 匹配前一个字符0或无限次

+ 匹配前一个字符1或无限次

? 匹配前一个字符0或1次

{m} 匹配前一个字符m次

{m,n} 匹配前一个字符m至n次

  • 边界匹配

^ 匹配字符串开头

$ 匹配字符串结尾

A 仅匹配字符串开头

Z 仅匹配字符串结尾

正则表达式练习1 re.findall



text = '''2月份,各地继续落实地方调控主体责任,坚持因城施策,促进房地产市场平稳健康发展。
据初步测算,4个一线城市新建商品住宅销售价格环比上涨0.3%,涨幅比上月回落0.1个百分点。
其中:北京下降0.2%,上海和广州分别上涨0.3%和1.1%,深圳持平。
二手住宅销售价格环比上涨0.15%。其中:北京和深圳分别上涨0.2%和0.5%,上海和广州分别下降0.1%和0.2%。
31个二线城市新建商品住宅销售价格环比上涨0.7%,涨幅连续三个月相同;
二手住宅销售价格环比下降20.21%,降幅比上月扩大0.1个百分点。
35个三线城市新建商品住宅销售价格环比上涨10.4%,涨幅比上月回落0.2个百分点;
二手住宅销售价格环比上涨0.2%,涨幅与上月相同。'''



# 把上面这段话中的所有百分比数值提取出来

思路: 1. 后面是百分号结尾 2. 百分号前边一定是数字, 数字的位数不确定 ,至少有一个



import re
re.findall( r'd+.?d+%', text)  #方法一
re.findall('d+.d+%' ,  text)   #方法二
re.findall('[d.]*%', text)  #方法三



正则表达式练习2



text1 = """西楼尘 看过  2018-07-02
最费力的成长留在树上的只有壳,最狰狞的伤口留在皮肤的只有疤。
 
7596 有用 凌睿 看过  2018-08-02
或是被第三者插足,或是不受父母待见,或是被辞退,却共同组成了最温馨家庭。 
举报
 
4170 有用 九只苍蝇撞墙 看过  2018-06-11
那些说是枝一直致敬小津的人可以歇歇了。这次他拍了部让小津最深恶痛绝的今村昌平式的蛆虫电影。

举报
 
3627 有用 咯咯精 看过  2018-05-14
如果说爱你,还打你,那一定是说谎;如果爱你,就会像安藤樱一样紧紧抱住你。(沉溺于安藤樱的美色无法自拔

举报
 
3347 有用 姨妈的鸭 看过  2018-06-23
比起放下手机,这本电影在观影时需要观众做的第一步是:放下三观。"""



#提取“有用”前面的数字



re.findall(r"(d+) 有用" , text1)



#提取 数字+“有用”



re.findall(r"d+ 有用" , text1)



#提取日期



re.findall(r"d{4}-d{2}-d{2}",text1)



#把年月日分开



r1 = re.findall(r'(d+)-(d+)-(d+)', text1)



#提取用户名



re.findall(r"(S+) 看过",text1)



正则表达式练习3 提取天猫超市狗粮重量(t.findall、t.extractall




python 时间正则表达式 findall_目录名字中包含日期正则匹配


import pandas as pd
df = pd.read_excel('Product_details_test.xlsx')
t = df.TradeName.str


python 时间正则表达式 findall_字符串_02


t.findall(r'd+k?g',flags = re.I)  #这时用.findall()提取出来的重量是列表


python 时间正则表达式 findall_正则表达式_03


result_1 = t.extractall(r'(d+k?g)',flags = re.I)  # 自动添加一列索引列


python 时间正则表达式 findall_正则表达式_04


result = t.extract(r'(d+)(k?g)',flags = re.I)  # 重量和单位分开


python 时间正则表达式 findall_正则表达式_05


result_2 = t.extract(r'(d+k?g)',flags = re.I)  # 重量和单位在一列


python 时间正则表达式 findall_字符串_06


注意:

  • - pandas 中str属性支持正则表达式的方法整理
  • - contains 包含,返回bool类型, 包含规则返回真,否则返回假
  • - extract 按组提取, 必须加括号分组, 提取出匹配出来的第一个数据
  • - extractall 按组提取, 必须加括号分组, 提取出匹配到的所有数据
  • - findall 提取出匹配到的所有数据, 默认返回列表

爬取网络小说的逻辑:
1. 先爬取每一章节的链接
2. 测试其中一章节的爬取
3. 使用循环爬取所有的章节, 分别储存到一个txt文件中
4. 可以再试一下, 把整部小说保存到一个文档中去.

二、案例1:爬取剑来小说 (利用正则表达式解析)

网址:http://www.shuquge.com/txt/8659/index.html

思路:
1. 从目录页里面把所有的章节列表链接提取出来
2. 先随便找一个章小说, 爬取测试
3. 把代码组合成函数, 抓取一章内容的函数命名为get_one_page_content() 编写保存到本地文件的功能.
4. 对chapter_link中的每一个连接进行循环, 调用get_one_page_content()获取到章节的标题和章节的内容
5. 将标题和内容保存下来
6. 对所有的章节遍历保存整部小说

做法:

第1步:定义一个函数,实现功能: 传进去一个链接, 返回的小说标题、内容


def get_one_page_content(url):
    """功能: 传进去一个链接, 返回的就是小说的名称还有小说的内容"""
    import requests 
    import re
    # 添加Hearder
    headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'}
    #  先随便找一个章小说, 爬取测试
    r = requests.get(url ,headers = headers)
    # 改变编码
    r.encoding = r.apparent_encoding
    # 提取标题
    title = re.findall(r'<h1>(.*)</h1>', r.text)[0]
    # 懒惰模式匹配文章主题内容, 提取文本内容
    content = re.findall(r'<div id="content" class="showtxt">(.*?)</div>', r.text, flags=re.S)[0].replace(' ','').replace('<br/>','n')
    return title, content


难点:提取标题和内容(正则表达式部分)

技巧:点开某一章节,光标放在标题,右键-审查元素(找标题的位置)


python 时间正则表达式 findall_目录名字中包含日期正则匹配_07

快速定位标题的位置

技巧:点开某一章节,光标放在正文,右键-审查元素(找正文的位置)


python 时间正则表达式 findall_正则表达式_08

快速定位正文的位置

第2步:定义第2个函数,实现功能: 传入一本小说网址, 返回小说章节列表


def get_novel_chapter_link(url):
    """功能: 传入一本小说网址, 返回小说章节列表"""
    import requests 
    import re
    # 添加Hearder
    headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'}
    #  
    r = requests.get(url ,headers = headers)
    # 改变编码
    r.encoding = r.apparent_encoding
    #  编写正则表达式进行匹配, 提取章节列表
    chapter_link = re.findall(r'<dd><a href="(.*)".*</dd>' , r.text)
    return chapter_link


第3-1步:实现功能:传入一本网络小说的网址,小说每一章节都独立保存为一个txt文件,到本地文件夹“剑来小说”


# 1. 获取章节列表 http://www.shuquge.com/txt/8659/index.html
chapter_link = get_novel_chapter_link("http://www.shuquge.com/txt/8659/index.html")
import requests 
import os
import re
if not os.path.exists('剑来小说'):
    os.mkdir('剑来小说')
# 2. 对chapter_link 中的链接进行遍历
basic_link = "剑来"
n = 1 # 开始数字
for one_link in chapter_link:
    # 网址的拼接操作
    complete_link =  basic_link + one_link
    # 调用爬取一章内容的函数
    title, content = get_one_page_content(complete_link)
    f = open('./剑来小说/'+ str(n) +'.'+title+'.txt', 'w'  ) # 进入下层目录  title  和 .txt
    f.write(content) # 写入小说内容
    f.close() # 关闭文件
    print('已完成章节:', title)
    n += 1


python 时间正则表达式 findall_正则表达式_09


第3-2步:实现功能:所有章节保存到一个txt文件中


# 1. 获取章节列表 剑来
chapter_link = get_novel_chapter_link("剑来")
import requests 
import os
import re
if not os.path.exists('剑来小说'):
    os.mkdir('剑来小说')
# 2. 对chapter_link 中的链接进行遍历
basic_link = "剑来"
novel_content = ''
for one_link in chapter_link:
    # 网址的拼接操作
    complete_link =  basic_link + one_link
    # 调用爬取一章内容的函数
    title, content = get_one_page_content(complete_link)
    novel_content =  novel_content+title+'nn'+content+'nn'
#循环外部    
f = open('./剑来小说/'+'剑来.txt', 'w','encoding = utf-8'  ) # 进入下层目录  title  和 .txt
f.write(novel_content) # 写入小说内容
f.close() # 关闭文件


三、方法二:BeautifulSoup方法

  • Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.
  • Beautiful Soup是一个利用HTML或者XML来对内容进行解析的, 解析库
  • HTML的属性都具有结构上的层级关系, 而且有css和id属性, Beautiful Soup就是利用这样的关系进行 提取


python 时间正则表达式 findall_正则表达式_10

库的安装

import requests
from bs4 import BeautifulSoup


BeautifulSoup库的练习1:诛仙小说


url = "https://www.ibiquge.net/40_40039/19832200.html"
headers ={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'}
r = requests.get(url)
r.encoding = r.apparent_encoding
r


# 利用BeautifulSoup 这个类 ,把源代码创建成 Beautifulsoup 对象


bs = BeautifulSoup(r.text , 'lxml') # 两个参数 1. 把源代码字符串放进去 2 . 解析器


python 时间正则表达式 findall_目录名字中包含日期正则匹配_11

源代码

python 时间正则表达式 findall_正则表达式_12

使用Beautiful库轻轻松松就把标题和内容提取出来了

url = "https://www.ibiquge.net/40_40039/"
headers ={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'}
r = requests.get(url)
r.encoding = r.apparent_encoding
bs = BeautifulSoup(r.text, 'lxml')


python 时间正则表达式 findall_html_13

使用Beautiful库轻轻松松就可以把章节的链接列表提取出来

练习2:童话故事


html = """<html>
<head><title>标题:睡前故事</title></head>
<body>
<p class="title" id="alice">
<b>睡前故事</b>
<i>
作者:佚名
</i>
<i>
年代:未知
</i>
<i>
动机:讲故事
</i>
</p><div>
<a class="littleboy" href="http://example.com/bek" id="link0">罗恩</a>, 
</div>
<div class="good">
<p class="story">很久很久以前, 有三个小女孩; 她们的名字分别叫做
<a class="sister" href="http://example.com/elsie" id="link1">爱丽丝</a>, 
<a class="brother" href="http://example.com/lacie" id="link2">莱希</a> and
<a class="sister" href="http://example.com/tillie" id="link3">蒂莉</a>;
她们居住在井底.</p>
</div>
<p class="story">接下来故事马上就要开始了, 让我们一起走进她们的冒险故事! </p>
</body>
</html>"""


bs = BeautifulSoup(html, 'lxml')

bs.find_all('body') #获取主体部分

bs.find_all('a') #获取链接

bs.find_all(text = '罗恩') #获取文本

bs.find('a' , text = re.compile('爱')) #获取包含某部分文本的内容

bs.find_all('a', class_='brother') #指定class属性

bs.find_all('a', 'brother') #指定class属性

bs.find_all('a','sister')#指定class属性

bs.find_all('a', id='link3') #指定id属性

bs.find_all('a', href="http://example.com/bek") #指定href


python 时间正则表达式 findall_正则表达式_14

1

python 时间正则表达式 findall_正则表达式_15

2

正则表达式与BeautifulSoup库的结合使用

re.compile('bek')

bs.find_all('a', href=re.compile('bek')) #提取链接包含某部分的内容

bs.find('p', 'story') #指定class属性

story.findAll('a', 'brother')[0] #指定class属性


python 时间正则表达式 findall_正则表达式_16

正则表达式与BeautifulSoup库的结合使用

python 时间正则表达式 findall_html_17


四、案例:爬取哪吒之魔童降世电影的短评(利用Beautiful库解析)

哪吒之魔童降世 短评movie.douban.com

定义函数:实现功能:输入一页短评地址,将短评、有用人数、评论时间、用户名、用户主页、用户头像返回到一个DataFrame中


python 时间正则表达式 findall_字符串_18


def get_one_page_short(url):
    import requests
    import pandas as pd
    from bs4 import BeautifulSoup

    r = requests.get(url , headers= headers)

    bs = BeautifulSoup(r.text,'lxml')
    # 短评
    short = []
    for i in bs.find_all('span', 'short'):
        short.append(i.text)
    # 有用人数
    votes = []
    for i in bs.find_all('span', 'votes'):
        votes.append(i.text)
    # 评论时间
    comment_time = []
    for i in bs.find_all('span', 'comment-time'):
        comment_time.append(i.text.strip())
    # 用户名
    username = []
    for i in bs.find_all('span', 'comment-info'):
        username.append(i.find('a').text)
    # 用户主页
    index = []
    for i in bs.find_all('span', 'comment-info'):
        index.append(i.find('a')['href'])
    # 用户头像
    img = []
    for i in bs.find_all('div', 'avatar'):
        img.append(i.find('img')['src'])
    # 先新建一个空的DataFrame
    df = pd.DataFrame()
    df['用户名'] = username
    df['评论时间'] = comment_time
    df['有用人数'] = votes
    df['评论内容'] = short
    df['用户主页'] = index
    df['用户头像'] = img
    
    return df


python 时间正则表达式 findall_目录名字中包含日期正则匹配_19

效果

五、从DataFrame中导出用户头像图片链接,保存到本地


n = 1
import os
if not os.path.exists('用户头像'):
    os.mkdir('用户头像')
for  i in df.用户头像:
    print(i)
    r = requests.get(i , headers = headers)
    f = open('./用户头像/'+str(n)+'.jpg' , 'wb')
    f.write(r.content)
    f.close()
    n += 1