目标:爬取介个微信公众号文章的正文内容
https://mp.weixin.qq.com/s/DNtuRvc9NM88eBEX61IpAQ
(也就是红框框里面的内容啦~)
在浏览器网页界面,用熟悉的F12,及快捷键组合“Shift+Ctrl+c”,很容易就定位到正文内容的标签,是在一堆section标签,里的span标签里。
PS:在观察网页结构时,↓会留意到这个微信网页是有JavaScript加载的内容的(script就是描述js内容属性的典型标签~),但是!这次咱选择爬取的文字内容,并非包含在js相关标签内,试试看果然是这样的~
首先,什么是正则?-个人理解它是一种描述文本信息的语法结构;
那么,为什么要用正则呢?-我截取了一部分来自菜鸟教程的介绍:
正则其实应用广泛,在爬虫学习实践方面,我们可以用正则语法,去匹配定位网页编码中的字符内容;还可以用正则语法进行字符串内的截取、替换操作,从而获得规整(理想)格式的字符串数据;比较于bs库、lxml库的网页内容定位,用正则语法的方式也可以发挥同样的内容定位作用。
详细的可以详阅菜鸟编程:
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\)\;\"\>(.*?)\<\/span\>' #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\)\;\"\>(.*?)\<\/span\>' ,html.text)
print(content)
for i in content:
i=i.replace('
','')
with open(file,'a') as f:
f.write(i+'\n')
前面说了,该网页虽然有js,但本次待爬取的正文内容不受影响,那么前面讲过的两种定位方式beautifulsoup和xpath应该都OK的,这两种方法这里也不细讲了,直接看看代码和效果叭~
可以看到,非常高效、美观,对比re正则的,没有多余的占位符出来
也还可以,不过xpath把占位符都解析出来了(占位符里没有内容,所有就None哈~),就没那么干净啦~