- 假期没事干,便萌生了学习网页爬虫的想法,这篇文章主要是用来记录学习过程,以及遇到的坑
前期准备
- 首先要选取一个适合爬虫的网站,这里选择的是神奇宝贝百科的技能列表,我们的目标是通过爬虫获取所有第一世代的普通系技能
- 在正式开始之前,要先确保电脑上有Python环境,可以使用
python --version
查看 - 之后通过
pip3 install bs4
和pip3 install requests
来安装我们需要用到的两个包,做好这些我们就可以开始正式写代码了
开工
- 在建立.py文件之后,我们首先要引入刚刚安装好的两个包:
import requests from bs4 import BeautifulSoup
- 在获取网页数据之前,我们需要给网页发送一个request请求,这个需要我们手动设置一下header请求数据
- 如图找到Network-Doc满就可以获得你发送的header‘请求了
- 这里我们把这个请求复制下来就可以了
-
#请求头部信息 headers = { 'user-agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36' }
- 下面只要我们发送请求获取数据就可以了,但是pyhton没办法解析中文url,这里就需要我们手动进行转码了:
-
from urllib import parse # 将链接中的中文解码 url = 'https://wiki.52poke.com/wiki/{}'.format(parse.quote('招式列表')) res = requests.get(url, headers = headers) # BeautifulSoup对象接收html文档字符串 # lxml是html解析器 soup = BeautifulSoup(res.text, 'lxml')```
- 工欲善其事必先利其器,在爬去网页数据前,我们需要分析网页的组成形式
可以看到,我们要获取的招式名称在一个
table
标签下,并且这个table
拥有一个独特的class
叫bg-关都
,通过beautifulsoup给定的find()
和find_all()
函数我们可以找到整个table
,下面我们来看下这个函数:
find()&find_all()
find( name , attrs , recursive , string , **kwargs )
find_all( name , attrs , recursive , string , **kwargs )
name 参数可以查找所有名字为 name 的tag,字符串对象会被自动忽略掉.
keyword 参数 如果一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作指定名字tag的属性来搜索
通过 string 参数可以搜搜文档中的字符串内容.与 name 参数的可选值一样, string 参数接受 字符串 , 正则表达式 , 列表, True .
limit 参数
find_all() 方法返回全部的搜索结构,如果文档树很大那么搜索会很慢.如果我们不需要全部结果,可以使用 limit 参数限制返回结果的数量.效果与SQL中的limit关键字类似,当搜索到的结果数量达到 limit 的限制时,就停止搜索返回结果.
recursive 参数
调用tag的 find_all() 方法时,Beautiful Soup会检索当前tag的所有子孙节点,如果只想搜索tag的直接子节点,可以使用参数 recursive=False .
引自beautiful soup文档
- 这两个函数可以从网页中获取我们需要的节点,也就是说,爬取数据的第一步可以利用这两个函数实现,也就是获取整个第一世代的技能表:
eplist = soup.find('table', class_ = 'bg-关都')
- 继续往下看,我们想获取的是第一世代所有普通系的技能。每一个技能在这个表里占一个
tr
标签,技能的属性由tr
标签下的一个<td class = 'bg-一般'></td>
标签表示,我们可以通过获取eplist
下的所有具有class = 'bg-一般'
的td
标签来找到我们目标技能,并通过获取他的父元素来找到我们需要的tr
,代码如下:
# 找出eplist下class属性为bg-一般的td
move_list = eplist.find_all('td', class_ = 'bg-一般')
# 将目标td的父元素,即所求tr加入目标数组
target = []
for i in move_list:
target.append(i.parent)
- 最后我们只要把目标文档输出到文件里就可以了,代码如下:
# 输出
file_name = './moves.txt'
with open(file_name, 'w+') as f:
for i in target:
temp = i.find('a')
print(temp.string)
f.write(str(temp.string))
f.write('\n')
运行结果如下
数据成功爬取,成了