爬取网易新闻
在本小节的内容中呢,笔者将会给大家讲述如何去过滤我们所不需要的内容。下面的例子,是本人在爬取网易新闻时,遇到的一个小问题,在定位元素之后,进行打印的时候,出现了部分内容无法正常解析。笔者也是进行了很长时间的尝试,请教了很多人,才得到的三种方法。我们一起来看。
通过写入文件的方法过滤元素
import requests
import re
from bs4 import BeautifulSoup as bs
response = bs(requests.get('http://news.163.com/16/0712/17/BRPSKEFP0001121M.html').text,'html.parser')
print('文章标题:',response.h1.string)
#print(response.h2.string)
#定位到含有('a',{'target':'_blank'})的元素,并输出里面的text元素
print("文章来源:",response.find('a',{'target':'_blank'}).text)
#通过find_all方法遍历(('div',{'id':'endText'})的内容,通过for循环,打印出div中所有的内容
for style in response.find_all('div',{'id':'endText'}):
# 通过for循环写入style中的text内容到F文件
with open("aa.txt",'a') as f:
f.write(style.get_text())
#通过for循环,写入到文件aa.txt,将f中的所有的iframe过滤
with open('aa.txt','r') as f:
for i in f :
if 'iframe' in i:
pass
else:
print(i)
好的,代码如上。我们接下来解读一下这段代码
首先,我们导入了requests库和bs4的方法,然后通过bs4的方法,解析了我们爬取到的网易新闻的内容
然后,就可以开始使用bs4中的方法,进行打印我们想要获得的内容了。
在这里,我们首先定位到h1打印了新闻标题,接着,使用find方法,找到了文章的来源
最后,通过find_all的方法,遍历了符合('div',{'id':'endText'})的标签下的所有内容,通过for循环去循环写入到aa.txt的文件,再加入一个for循环与一个if的判断,遍历aa.txt的文件,然后过滤掉文件中所有带有iframe的内容。
这里是,是由于,我之前写的时候,定位到了正文内容,但是输出的时候,总是无法输出所有的正文,想到的取代的方法。那么接下来会有另外两种方法,也来介绍给大家。
通过正则表达式过滤元素
在上面那段代码中,由于本人学艺不精,最初只能通过那种方法,进行过滤,下面我们来看看如何使用正则表达式,去过滤掉我们不需要的内容。
#通过正则表达式,过滤屌所有的不符合条件的html的标签,使用re.sub,进行替换,然后打印出过滤完成的内容
#response = response = bs(requests.get('http://news.163.com/16/0712/17/BRPSKEFP0001121M.html').text
#clear = re.compile('<s*script[^>]*>[^<]*<s*/s*scripts*>',re.I)
#content = clear.sub("",response)
#soup = bs(content,'html.parser')
#content = soup.find('div',{'id':'endText'})
#print(content.text.strip())
如果你有访问这个新闻链接,并且进行过调试,就会看到,在我定位的div的元素中,是包含了另一个script的。那么在这里呢,我们通过了正则表达式,对返回的内容中的script里的内容进行定位,并且通过,r.sub的方法,将返回内容中的script进行了替换,全部替换为了空的。
当然,这部分的难点就在于如何去编写这个正则表达式。笔者其实最初是有考虑过使用正则去实现过滤的,但是也是苦于不会编写,无奈只能放弃。正则的话,各位也只能多练了。
使用lxml解析库进行解析
经过多次的尝试,笔者终于发现了问题所在,原来是解析库使用错误导致了解析的时候出现了一些小问题。不过没关系,我们也掌握了另外两个方法。下面这段代码就是我们使用lxml的解析库的的方法。
#使用lxml解析库,对爬到的页面进行解码
#response = bs(requests.get('http://news.163.com/16/0712/17/BRPSKEFP0001121M.html').text,'lxml')
#print('文章标题:',response.h1.string)
#print("文章来源:",response.find('a',{'target':'_blank'}).text)
#soup = response.find('div',{'id':'endText'}).find_all('p')
#for i in soup:
# print(i.text)
OK,运行上述代码之后,我们会发现,输出的结果和使用正则过滤的是一样的。那么,为什么会这样呢?
我们都知道,Beautiful Soup包含了并不止一种的解析库,而笔者之前使用的是html的解析库,也就导致了,之前出现了部分script无法解析,过滤的情况。至于原因,目前笔者也是无法解释清楚。不过呢,我们不要纠结于此。这次只是一个小小的教训,也希望大家记住,当我们在使用一个库无法达到想要的效果的时候,不妨尝试另一个库,也许会有惊喜哦。
上面的三种方法,都可以得到我们想要的结果。
在这里呢,只是想告诉大家,大道万千,殊途同归。实现的方法,有很多种;而我们,并不需要大家全部掌握,只需要能够使用适合自己的就好。