1、常用的方法
re模块提供了下面的方法进行字符串的查找、替换和分割等各种处理操作
方法 | 描述 | 返回值 |
---|---|---|
compile(pattern[, flags]) | 提升查找效率,它可以调用match()等方法,但不可再次调用compile方法 | re对象 |
search(pattern, string[, flags]) | 在字符串中查找任意地方开始匹配 | 第一个匹配到的对象或者None |
match(pattern, string[, flags]) | 在字符串的开头开始匹配 | 在字符串开头匹配到的对象或者None |
split(pattern, string[, maxsplit=0,flags]) | 根据自定义的re字符串,来分割字符串 | 分割后的字符串列表 |
findall(pattern, string,flags) | 列出字符串中模式的所有匹配项,无group()方法 | 所有匹配到的字符串列表,有分组时返回的是分组的结果 |
sub(pat,repl, string[,count=0,flags]) | 将字符串中所有的pat的匹配项用repl替换,使用\1表示分组1中的字符;同理\2则是分组2中的字符;注意\\表示\,所以需要写成\\1; | 完成替换后的新字符串 |
2、flags匹配模式
Python的re模块提供了一些可选的标志修饰符来控制匹配的模式。可以同时指定多种模式,通过与符号|来设置多种模式共存。如re.I | re.M被设置成I和M模式。
匹配模式 | 描述 |
---|---|
re.A | ASCII字符模式 |
re.I | 使匹配对大小写不敏感,也就是不区分大小写的模式 |
re.L | 做本地化识别(locale-aware)匹配 |
re.M | 多行匹配,影响 ^ 和 $ |
re.S | 使 . 这个通配符能够匹配包括换行在内的所有字符,针对多行匹配 |
re.U | 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B |
re.X | 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解 |
常用的flags有re.I、re.S
3、分组功能
group使用 | 意义 |
---|---|
.group() | 返回刷选出来的字符串 |
.group(1) | 进行分组后,返回第一组的值 |
.groups() | 将分组后的结果,存入一个元组中返回 |
.grouplist() | 通过给分组命名,然后以字典形式返回 |
给分组命名:?P<分组名>,比如:re.match(r”(?P
使用小括号进行分组
**
例1,findall()方法,没有分组的情况:
import re
origin = "has something have do"
# 无分组
r = re.findall("h\w+", origin)
print(r)
执行结果:
['has', 'hing', 'have']
例2,findall()方法,有一个分组的情况:
import re
origin = "has something have do"
# 一个分组
r = re.findall("h(\w+)", origin)
print(r)
执行结果:
['as', 'ing', 'ave']
例3,findall()方法,有两个以上分组的情况:
import re
origin = "hasabcd something haveabcd do" # 字符串调整了一下
# 两个分组
r = re.findall("h(\w+)a(bc)d", origin)
print(r)
运行结果:
[('as', 'bc'), ('ave', 'bc')]
4、如何拆分含有多种分隔符的字符串
第一种方法,可以连续使用str.split()方法,每次处理一种分割符号
def mySplit(s,ds):
res = [s]
for d in ds:
t = []
list(map(lambda x:t.extend(x.split(d)),res))
res = t
return res
s = 'ab;cd|efg|hi|hi,jkl\topq;str,ubw\x07syd'
print(mySplit(s,',;|\t'))
如果出现连续的分割符号,会出现空字符的情况,这时候如果我们想去掉空字符串。
return [x for x in res if x]
用列表推导式可以完成这个需求。
第二种方法,使用正则表达式的re.split()方法,一次性拆分字符串
import re
re.split(r'[,;\t|]+',s)
某软件要求,从网络抓取各个城市气温信息,并依次显示
北京:15-17
天津:17-22
长春:12-18
如果一次抓取所有城市天气再显示,显示第一个城市气温时,有很高的延迟,并且浪费存储空间,我们期望以用时访问的策略,并且能把所有城市气温封装到一个对象里,可用for语句进行迭代,如何解决?
import requests
def getWeather(city):
r = requests.get('http://wthrcdn.etouch.cn/weather_mini?city='+city)
data = r.json()['data']['forecast'][0]
return '%s:%s,%s'%(city,data['low'],data['high'])
print(getWeather('北京'))
5、文件名中特殊字符的替换
文件名不能含有以下字符串 \ / : * ? “ < > |
使用正则表达式的re.sub()方法,将这些字符串替换成空字符串(“”)或者其他正常字符;
re.sub(r"[\/\\\:\*\?\"\<\>\|]", "", "要替换的字符串")
6、请求头加引号
- 使用re.sub() ```c import re
headers = “””
“”” pattern = r”^(.?): (.)$” for line in headers.splitlines(): headers_format = re.sub(pattern, “\’\1\’: \’\2\’,”, line) print(headers_format)
**
<a name="Dj6nc"></a>
### 小说案例
```python
import requests
import re
import os
class NovelSpider(object):
def __init__(self):
self.burl = "https://www.biquga.com/36_36169/"
self.headers = {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"Accept-Encoding": "gzip, deflate, br",
"Accept-Language": "zh-CN,zh;q=0.9",
"Cache-Control": "no-cache",
"Connection": "keep-alive",
"Host": "www.biquga.com",
"Pragma": "no-cache",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "cross-site",
"Sec-Fetch-User": "?1",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36"
}
self.content_headers = {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"Accept-Encoding": "gzip, deflate, br",
"Accept-Language": "zh-CN,zh;q=0.9",
"Cache-Control": "no-cache",
"Connection": "keep-alive",
"Host": "www.biquga.com",
"Pragma": "no-cache",
"Referer": "https://www.biquga.com/36_36169/",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "same-origin",
"Sec-Fetch-User": "?1",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36"}
def get_burl(self):
print("get url...")
res = requests.get(self.burl, headers=self.headers)
print(res.status_code)
re_str = r'<dd><a href="(.*?)".*?>(.*?)</a></dd>'
re_book = re.findall(re_str, res.text, re.S)
content_url_list = []
content_name_list = []
for data in re_book:
content_url = "https://www.biquga.com" + data[0]
content_name = data[1]
if "\\" in content_name:
print(1111111111)
content_name.replace("\\", "")
content_name_list.append(content_name)
content_url_list.append(content_url)
if re_book.index(data) == 100:
break
print("get done")
return content_url_list, content_name_list
def content(self, content_url_list, content_name_list):
print("get content...")
book_content = {}
for i, content_url in enumerate(content_url_list):
res = requests.get(content_url, headers=self.content_headers)
print(res.status_code)
re_str = r'<div id="content" name="content">(.*?)</div>'
book_content[content_name_list[i]] = re.findall(re_str, res.text, re.S)[0].strip().replace("<p>", " ").replace("</p>", "\n\n")
print("get done")
return book_content
def save_book(self, book_content):
print("save...")
if not os.path.exists("novel"):
os.mkdir("novel")
for name, book in book_content.items():
print(name, book)
filename = "novel/{}.txt".format(name)
with open(filename, "w", encoding="utf-8") as f:
f.write(book)
print("save done")
def run(self):
# 1 获取每个章节的url和名字
content_url_list, content_name_list = self.get_burl()
# 2 根据url获取章节内容
book_content = self.content(content_url_list, content_name_list)
# 3 保存章节内容
self.save_book(book_content)
if __name__ == '__main__':
bookspider = NovelSpider()
bookspider.run()