起因
最近打算自己做一个安卓app,因为实在是没有可以拿出手的项目了,再这样下去技能也会荒废掉。然而作为一个独立的开发者,我不得不自己来提供后端的接口,这就意味着我得尝试着学习一下后端的知识。
最后决定用python来做,因为python应该是使用非常广泛的一种语言,在很多地方都可以用上,学会一些肯定很不错。在学习了一些基础的知识后,发现python可以用脚本在网页上爬取信息,这意味着我可以从网上获取内容填充到我的数据库里面,而不用自己手动添加了(之前我都不知道数据库里面的内容是怎么来的,难道一定要再建立一个前端的输入页面吗)。总之我后面就发现了一个叫做beautifulsoup的库,可以比较方便的提取信息。
目标
前段时间一直在玩“只狼”,所以这次打算去游民星空上面爬取一些关于只狼的资讯信息。我接下来就准备获取下图里面的这几个标题。
开始动手
1.导入基本的包
from bs4 import BeautifulSoup #是一个可以从HTML或XML文件中提取数据的Python库
from lxml import html #lxml是一个用来解析网页元素的库
import requests #requests是一个涉及到网络请求的库
2.尝试看看是否能成功解析网页
url = "https://www.gamersky.com/z/sekiro/news/"
f = requests.get(url) #Get该网页从而获取该html内容
soup = BeautifulSoup(f.content, "lxml") #用lxml解析器解析该网页的内容
print(soup.prettify()) #prettify()方法将BeautifulSoup的文档树格式化后以Unicode编码输出,每个XML/HTML标签都独占一行
先输入你想解析的网页,然后使用prettify()方法,看看能不能成功解析该网页。我最后得到了以下返回值,如图:

通过这个图我们可以发现,我们已经初步获取了网页的架构,说明解析也是成功的,现在我们需要获取具体的我们想要的信息。
注意:有时候有些网页的内容是需要登录或者某些用户权限的,这个时候就涉及到一些别的机制了,我暂时还没有掌握,所以就找了个相对简单的网页作为爬虫样例。
3.根据节点名称来筛选出想要的内容
在chrome浏览器里面按F12可以打开控制台,利用页面审查的工具,可以发现,我想要的新闻标题里面的class='tit',我就想先用这个作为搜索的依据。

for k in soup.find_all('div',class_="tit") : #找到div并且class为tit的标签
print(k.text)
运行代码后,发现出现的结果并不完美。


我只想获取标题列表,为什么会出现很多无关的内容呢。仔细检查以后发现,原因是div的类名定义的太宽泛了,有部分别的内容的class也是'tit',导致了筛选出了多余的内容。


所以说我应该缩小筛选的范围,使其更加精确。
4.重新筛选--使判断条件更加精确

再次观察以后可以发现,我们需要内容都是在一个class='li1'的<li>标签下面的,我们可以搜索所有的class为'li1'的li标签,然后获取其内部的a标签里面的文字。
for k in soup.find_all('li',class_="li1") : #,找到li并且class为li1的标签
a = k.find_all('a') #在每个对应li标签下找a标签
print(a[0].string) #获取a标签下的第一个字符串
最后获得了纯粹的新闻标题列表,实现了目标。

完整代码如下
from bs4 import BeautifulSoup
from lxml import html
import requests
url = "https://www.gamersky.com/z/sekiro/news/"
f = requests.get(url) #Get该网页从而获取该html内容
soup = BeautifulSoup(f.content, "lxml") #用lxml解析器解析该网页的内容
#print(soup.prettify()) #prettify()方法将BeautifulSoup的文档树格式化后以Unicode编码输出,每个XML/HTML标签都独占一行
for k in soup.find_all('li',class_="li1") : #,找到li并且class为li1的标签
a = k.find_all('a') #在每个对应li标签下找a标签
print(a[0].string) #获取a标签下的第一个字符串
总结
真的是非常简单的一次运用了,但是第一次用还是折腾了不少时间。如果能熟练运用正则表达式的话,应该可以做到更加精确的查询。
网友评论