python网页数据抓取(【干货】正则表达式在python中的强大用处(一))
优采云 发布时间: 2022-01-08 20:25python网页数据抓取(【干货】正则表达式在python中的强大用处(一))
这是东耀日报的第33天文章
东瑶写作的目的文章:分享东瑶的经验和思考,帮助你实现物质和精神的双重幸福。
昨天我们讲了一些常用的正则表达式语法规则,那么今天东耀就用实例来讲解正则表达式在python中的强大使用。
1
正则表达式常用函数和方法
在python中使用正则表达式需要导入正则表达式模块(re),它是python的内置模块,所以不需要安装,但是需要注意的是我们不要使用这个名字命名文件时,否则会导致模块名冲突,使其无法使用。
re中的flag参数及其含义
1.忽略大小写(常用)
I=IGNORECASE=sre_compile.SRE_FLAG_IGNORECASE
2.\w、\W、\b、\B等是否生效取决于当前系统环境(其实没用)
L=LOCALE=sre_compile.SRE_FLAG_LOCALE
3. 匹配Unicode字符串,主要针对非ASCII字符串,因为python2默认的字符串都是ASCII编码的,所以模式\w+可以匹配所有ASCII字符。\w+ 匹配 Unicode 字符,你可以设置这个标志
U=UNICODE=sre_compile.SRE_FLAG_UNICODE
4.多行匹配,主要是匹配行首(^)或行尾($)的时候,如果不使用多行匹配,多行文本不能匹配成功
M=MULTILINE=sre_compile.SRE_FLAG_MULTILINE
5.让句点(.)也代表换行(常用)
S=DOTALL=sre_compile.SRE_FLAG_DOTALL
6.忽略表达式模式中的空格和注释
X=VERBOSE=sre_compile.SRE_FLAG_VERBOSE
2
爬虫实战案例
以散文网“”为例,东耀将演示如何使用正则表达式提取散文网上的文章标题、URL等内容。示例网页内容包括文章标题、文章url等,原网站内容截图如下:
下一步是使用python爬虫来爬取网页内容:
1
导入模块
re 模块:python 内置的正则表达式模块
请求模块:http请求模块
urllib.request:里面的headers主要用来模拟浏览器请求
2
模拟浏览器请求
有的网站有反爬机制,也就是说网站服务器会通过User-Agent的值来判断是否是浏览器的请求。当我们使用python爬虫爬取内容时,如果不设置User-Agent的值来模拟浏览器请求,则可能会拒绝访问网站,内容将无法爬取。
因此,在做网络爬虫的时候,一般会使用urllib.request模块中的headers方法来模拟浏览器请求,从而让网站服务器对我们的爬虫开放。
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, 像 Gecko) Chrome/63.0.3239.132 Safari/537.36'}
req = urllib.request.Request('#x27;,headers=headers)
# html存储整个页面内容
html = requests.get('#x27;)
html = html.text
3
获取网页内容
使用 requests 模块的 get 方法将网页内容获取到自定义变量中。这里需要注意的是,requests返回的是一个response对象,里面存储了服务器响应的内容。如果我们要使用内容,还需要使用 text 方法来解码响应的文本编码(见下图 2)。html的区别,一是响应对象,二是实际网页内容)。
4
使用正则表达式匹配页面标题(title)
通过对源码的观察,我们发现需要的网页标题title就是放置在中间的文本内容,那么我们需要使用正则表达式来匹配内容:'(.*?)'。将需要提取的内容用括号分组,方便后面提取分组的内容,用“.*?”过滤不需要的内容。
这里有同学可能会问,为什么要用“.*”?而不是“。*”来匹配?这是因为“.*”是一个贪心模式,此时会尽可能匹配,同时添加? 将尽可能少地匹配。例如,我们现在有以下文本:
经典散文_经典文章赏析_散文网
我们可以看到它收录了3对组合,也就是说有3个title,那么此时使用“.*”的匹配结果会从第一个开始,到最后一个结束,都是匹配进去:
如果 ?添加后,会以pairs的形式一一匹配,结果如下:
所以我们在匹配的时候一定要注意贪心模式和非贪心模式的区别。如果不确定匹配结果,可以将网页内容复制到 sublime 中,尝试编写正则表达式进行匹配。正则表达式被写入python。
编译方法:
compile方法是对正则表达式的匹配模式进行预编译,然后生成缓存,这样缓存可以直接用于后续的匹配,不需要每次匹配都重新编译,从而加快速度。
一般情况下,只有在重复使用一个正则表达式时,才需要使用compile方法提前编译。如果只使用一次,则没有必要。请看下图使用compile方法预先编译和不使用compile方法的区别:
group() 和 groups() 的区别:
groups 方法返回所有匹配的子组,并返回一个元组。group 方法返回所有匹配的对象。如果我们只想要子组,我们需要添加参数。请看下图两种结果的对比:
5
使用正则表达式匹配 文章 标题(article_title)
正则表达式的写法和以前一样。我这里要介绍的是findall方法:使用findall方法匹配所有符合要求的字符串。findall 方法返回一个列表。一个例子如下:
然后我们可以使用findall方法匹配网页中所有匹配的内容并存储到列表中,然后通过for循环提取列表内容:
6
使用正则表达式匹配 文章url(article_url)
可以看出,直接获取列表中的文章url得到的结果是一个相对路径,所以我们需要使用一些方法来补全路径。这里东耀为大家介绍两种方法:
第一个是列表理解:
第二种是使用正则表达式的sub或subn方法替换字符串:
7
关于大小写匹配和换行符匹配
有时候我们在匹配的时候可能会出现不区分大小写的错误,那么我们在匹配的时候怎么能不区分大小写呢?re 模块中的标志参数 I 用于忽略大小写匹配。用法如下:
有时某些内容在匹配时涉及换行符,以及“.”。只能匹配除换行符以外的所有字符。如果你想匹配换行符,你需要在 re 模块中使用标志参数 S。用法如下: