爬虫入门实战系列(六)正则/bs4/xpath比较-爬取公众号文章正文

Psyche ·
更新时间:2024-11-10
· 760 次阅读

目标:爬取介个微信公众号文章的正文内容

 https://mp.weixin.qq.com/s/DNtuRvc9NM88eBEX61IpAQ

(也就是红框框里面的内容啦~)

先观察一波网页结构

在浏览器网页界面,用熟悉的F12,及快捷键组合“Shift+Ctrl+c”,很容易就定位到正文内容的标签,是在一堆section标签,里的span标签里。

PS:在观察网页结构时,↓会留意到这个微信网页是有JavaScript加载的内容的(script就是描述js内容属性的典型标签~),但是!这次咱选择爬取的文字内容,并非包含在js相关标签内,试试看果然是这样的~

学习使用正则爬取 简述正则

首先,什么是正则?-个人理解它是一种描述文本信息的语法结构;

那么,为什么要用正则呢?-我截取了一部分来自菜鸟教程的介绍:

正则其实应用广泛,在爬虫学习实践方面,我们可以用正则语法,去匹配定位网页编码中的字符内容;还可以用正则语法进行字符串内的截取、替换操作,从而获得规整(理想)格式的字符串数据;比较于bs库、lxml库的网页内容定位,用正则语法的方式也可以发挥同样的内容定位作用。

py爬虫中的正则用法

详细的可以详阅菜鸟编程:

Python 正则表达式

这里咱参考菜鸟编程的说明,选择性介绍:

1.首先我们需要引入re模块(库),从而为python提供完整地正则表达式功能;

2.使用re.match()函数可以从字符串的起始位置(因为有这个限制,用起来似乎不大灵活,就不详叙哩~),匹配符合要求正则语法的字符串。

3.使用re.search()函数,可以扫描整个字符串,并返回第一个成功的匹配(但只能匹配第一个,爬虫一般也是匹配多个相同规则的内容,也不详述哩~)

*4.使用re.sub(),可以替换/删除字符串中的匹配项,咱一般直接用str下面的.replace()方法去实现同样的操作,检索查询了解到re下的.sub()方法稍微更强大一些,比如可以把多种不同类型的字符统一替换、删除。

另外str字符串处理相关的.strip()、.split()、.join()方法也是极为常用的,.strip()可以高效处理字符串首尾的空格、换行等多余占位符;.split()可以根据字符串中的分隔符,将单一字符串拆分;.join()则可以将多个字符串合并,并且可以选择插入间隔分隔符。

5.re.compile()函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。(后面这俩这里不细说,这个也不细说啦~)

*6.re.findall()函数,用于在字符串中找到正则表达式所匹配的所有子串,并返回一个列表(返回list类型),如果没有找到匹配的,则返回空列表。这个咱用的最多,可以一次匹配所有符合正则表达式的字符串内容~

类似的re.finditer(),在字符串中找到正则表达式所匹配的所有子串后,则以迭代器的方式返回(也就是要用for...in...来遍历读取结果)。

另外列一些常用的正则表达式语法:

^ 匹配字符串的开头
$ 匹配字符串的末尾。
. 匹配任意字符,除了换行符
[^...] 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。
re* 匹配0个或多个的表达式。
re+ 匹配1个或多个的表达式。
re? 匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式
re{ n, m} 匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式
a| b 匹配a或b
(re) 对正则表达式分组并记住匹配的文本
\s 匹配任意空白字符,等价于 [\t\n\r\f].
\S 匹配任意非空字符
\d 匹配任意数字,等价于 [0-9].
\D 匹配任意非数字

特别要提贪婪匹配和非贪婪匹配,贪婪匹配就是为了不漏就尽可能多的匹配,往往通过在表达式内,尤其末尾加*号来实现,因为*号代表可以匹配0到多个符合正则表达式的字符串;非贪婪匹配则常通过搭配?号实现,即匹配0个或1个就好了(知足哈~)。 

正则实战爬取部分

先requests一波获取返回请求,没带headers也过了哈哈,返回200系。

import requests url='https://mp.weixin.qq.com/s/DNtuRvc9NM88eBEX61IpAQ' html=requests.get(url) html

引入re库,写一下正则规则,然后从html.text,即网页编码文本从匹配所有符合项: 

import re content=re.findall(r'rgb\(63\, 63\, 63\)\;\"\>(.*?)\<\/span',html.text) content #看一下content列表里的内容,发现正文应该都在里面了,虽然还有一些无关的占位符标签

这里的正则表达式是这么写的呢?

首先咱观察一下html.text,并复制一截正文内容,使用ctrl+f手动查找定位到字符串附近,然后观察发现正文字符串都为一个span标签包裹着(注意看涂黄部分,有规律滴~)//这个手动定位过程和在浏览器控制台的定位是一样的哈~

咱复制一段下来,包含正文内容的各个span标签差不多都这样子:

2月7日晚上,西安高...的通知:

书写对应的正则,是这样个过程:

2月7日晚上,西安高...的通知: r'' #1先一个转义字符r和'' r'rgb(63, 63, 63);">2月7日晚上,西安高...的通知:' #2把正文及两侧的标签内容复制进'',咱这里右边是完整的,左边没整完整的,嫌长,只要复制到的两侧内容是独特的就不一定要完整放入 r'rgb(63, 63, 63);">(.*?)' #3把正文内容用正则语法替换,注意要非贪婪模式,贪婪模式也可以试试哈 r'rgb\(63\, 63\, 63\)\;\"\>(.*?)\' #4在原来两侧标签所有符号前面添加转义符\,把特殊符号都转译成程序能识别的;于是就写完收工~

.findall()找到html.text中的正则后,print一下↑,其实正文内容已经都在content这个列表里了,但还有一些多余的
占位符,于是咱就遍历content这个列表,然后把占位符用空字符replace掉(就是删了它啦~),然后用之前讲过的with open方式,写入到txt文件中,打开新产生的文件,就是图右的效果啦~ 

附code:

import requests import re url='https://mp.weixin.qq.com/s/DNtuRvc9NM88eBEX61IpAQ' html=requests.get(url) html.text file='C:/Users/lgb11/Desktop/wenzhang.txt' content=re.findall(r'rgb\(63\, 63\, 63\)\;\"\>(.*?)\' ,html.text) print(content) for i in content: i=i.replace('
','') with open(file,'a') as f: f.write(i+'\n')
最后用bs4和xpath另外两种定位方式比较看看

前面说了,该网页虽然有js,但本次待爬取的正文内容不受影响,那么前面讲过的两种定位方式beautifulsoup和xpath应该都OK的,这两种方法这里也不细讲了,直接看看代码和效果叭~

先是beautifulsoup的

可以看到,非常高效、美观,对比re正则的,没有多余的占位符出来

然后是xpath的

也还可以,不过xpath把占位符都解析出来了(占位符里没有内容,所有就None哈~),就没那么干净啦~

咚唔 原创文章 15获赞 3访问量 621 关注 私信 展开阅读全文
作者:咚唔



公众号 爬虫 实战 正则 XPath

需要 登录 后方可回复, 如果你还没有账号请 注册新账号