精通python爬虫-step2基本库的使用-re正则表达式

正则表达式

通过一个模式pattern去匹配文本的内容,提炼出自己想要的数据;
需要应用re这个库。

1.match()方法

从字符串的开头开始匹配,匹配到了就返回第一个匹配到的内容,如果一开始就不匹配就返回None。

import  re
content="Hello 123 4567 World_This is a Regex Demo"
result=re.match('^Hello\\s\\d\\d\\d\\s\\d{4}\\s\\w{10}',content)
print(result.group()) #返回Hello 123 4567 World_This
print(result.span()) #span()方法会返回匹配的索引,返回匹配的位置(0,25)

2.group()方法会返回匹配的内容

如果想要匹配某个目标,可以使用括号着重标记,括号的作用是标记一个子表达式的开始和结束位置,被标记的子表达式会依次对应一个分组,调用group()方法传入索引可以获得提取的结果
比如

content="Hello 123 4567 World_This is a Regex Demo"

想要用表达式去匹配以上这个内容

pattern='^Hello\\s\\d{3}\\s\\d{4}\\s\\w{10}\\s\\w{2}\\s\\w\\s\\w{5}\\s\\w{4}'
import  re
content="Hello 123 4567 World_This is a Regex Demo"
result=re.match('^Hello\\s\\d{3}\\s\\d{4}\\s\\w{10}\\s\\w{2}\\s\\w\\s\\w{5}\\s\\w{4}',content)
print(result.group()) #返回完整的content

如果只需要返回数字

pattern='^Hello\\s(\\d{3})\\s\\(d{4})\\s\\w{10}\\s\\w{2}\\s\\w\\s\\w{5}\\s\\w{4}'
import  re
content="Hello 123 4567 World_This is a Regex Demo"
result=re.match('^Hello\\s(\\d{3})\\s(\\d{4})\\s\\w{10}\\s\\w{2}\\s\\w\\s\\w{5}\\s\\w{4}',content)
print(result.group(1)) #返回123
print(result.group(2)) #返回4567

3.search()方法

不局限于从字符串的开头开始匹配,匹配到了就返回第一个匹配到的内容。
1.如果运用match方法

import  re
content="Extra Hello 123 4567 World_This is a Regex Demo"
result=re.match('Hello\\s(\\d+)\\s',content)
print(result) #返回None

2.如果运用search方法

import  re
content="Extra Hello 123 4567 World_This is a Regex Demo"
result=re.search('Hello\\s(\\d+)\\s',content)
print(result) #返回<re.Match object; span=(6, 16), match='Hello 123 '>

4.贪婪匹配和非贪婪匹配

如果想获取content中的数字1234567
1.贪婪匹配.*

import  re
content="Hello 1234567 World_This is a Regex Demo"
result=re.match('^He.*(\\d+).*Demo$',content)
print(result.group(1)) #输出7

分析原因:
贪婪匹配会尽可能匹配更多,所以这里尽可能多的匹配到数字
2.非贪婪匹配.*?

import  re
content="Hello 1234567 World_This is a Regex Demo"
result=re.match('^He.*?(\\d+).*Demo$',content)
print(result.group(1)) #输出1234567

如果匹配的结果在字符串结尾,因为他尽可能少的匹配字符,所以.*?就匹配不到任何内容了
比如

content='http://weibo.com/comment/test'
result1=re.match('http.*?comment/(.*?)',content)
result2=re.match('http.*?comment/(.*)',content)
print(result1.group(1)) #返回空
print(result2.group(1)) #返回test

5.findall()方法

匹配字符串中所有符合模式pattern的内容,返回所有匹配项。
如果针对以下html内容

html='''<div id="songs-list">
<h2 class="title">经典老歌</h2>
<p class="intrpduction">
经典老歌列表
</p>
<ul id="list" class="list-group">
<li data-view="2">一路上有你</li>
<li data-view="7">
<a href="/2.mp3" singer="任贤齐">沧海一声笑</a>
</li>
<li data-view="4" class="active">
<a href="/3.mp3" singer="齐秦">往事随风</a>
</li>
<li data-view="6"><a href="/4.mp3" singer="beyond">光辉岁月</a></li>
<li data-view="5"><a href="/5.mp3" singer="陈慧琳">记事本</a></li>
<li data-view="5">
<a href="/6.mp3" singer="邓丽君">但愿人长久</a>
</li>
</ul>
</div>'''

针对以上的内容,提取歌手名字和歌名

re.S的作用

使得模式可以匹配到换行

1.不加re.S

result=re.search('<li.*?singer="(.*?)">(.*?)</a>',html)
if result:
    print(result.group(1),result.group(2))
    #输出beyond 光辉岁月

2.加re.S

result=re.search('<li.*?singer="(.*?)">(.*?)</a>',html,re.S)
if result:
    print(result.group(1),result.group(2))
    #任贤齐 沧海一声笑

search()只返回了一个内容
3.使用search

results=re.search('<li.*?href="(.*?)".*?singer="(.*?)">(.*?)</a>',html,re.S)
print(results) 
#输出<re.Match object; span=(121, 208), match='<li data-view="2">一路上有你</li>\n<li data-view="7">\>

4.使用findall()

results=re.findall('<li.*?href="(.*?)".*?singer="(.*?)">(.*?)</a>',html,re.S)
for result in results:
	print(result[0],result[1],result[2])#输出所有内容

6.sub()方法

指定模式pattern,对所有符合pattern的数据作替换,相比replace()方法功能更强大。

举例:将数字替换为空

content='54aK54yI5oiR54ix5L2g'
content=re.sub('\\d+','',content)
print(content) #输出aKyIoiRixLg

7.compile()方法

将模式pattern编译成一个可复用的模式,方便后续直接调用。

举例:去掉时间,保留日期

content1='2016-12-15 12:00'
content2='2016-12-17 12:55'
content3='2016-12-22 13:21'
pattern=re.compile('\\d{2}:\\d{2}')
result1=re.sub(pattern,'',content1)
result2=re.sub(pattern,'',content2)
result3=re.sub(pattern,'',content3)
print(result1,result2,result3)
#输出2016-12-15  2016-12-17  2016-12-22 

实例:抓取猫眼电影top100

import json
import re

import requests
import time
def get_one_page(url):
    headers={
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36 Edg/133.0.0.0'
    }
    response=requests.get(url,headers=headers)
    # print(f"状态码: {response.status_code}")
    if response.status_code==200:
        return response.text
    return None
def parse_one_page(html):
    pattern=re.compile('<dd>.*?board-index.*?>(.*?)</i>.*?data-src="(.*?)".*?name.*?a.*?>(.*?)</a>.*?star.*?>(.*?)</p>.*?releasetime.*?>(.*?)</p>.*?integer.*?>(.*?)</i>.*?fraction.*?>(.*?)</i>.*?</dd>',re.S)
    items=re.findall(pattern,html)
    for item in items:
        yield {
            'index':item[0],
            'image':item[1],
            'title':item[2].strip(),
            'actor':item[3].strip()[3:] if len(item[3])>3 else '',
            'time':item[4].strip()[5:] if len(item[4])>5 else '',
            'score':item[5].strip()+item[6].strip()
        }
def write_to_file(content):
    with open('result.txt','a',encoding='utf-8') as f:
        print(type(json.dumps(content)))
        f.write(json.dumps(content,ensure_ascii=False)+'\n')
def main(offset):
    url='http://maoyan.com/board/4'+'?offset='+str(offset)
    html=get_one_page(url)
    for item in parse_one_page(html):
        print(item)
        write_to_file(item)
if __name__ == '__main__':
    for i in range(10):
        main(offset=i*10)
        time.sleep(60)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值