任务描述
本次实践使用Python来爬取百度百科中《乘风破浪的姐姐》所有选手的信息,并进行可视化分析。
数据获取:https://baike.baidu.com/item/乘风破浪的姐姐
上网的全过程:
普通用户:
打开浏览器 --> 往目标站点发送请求 --> 接收响应数据 --> 渲染到页面上。
爬虫程序:
模拟浏览器 --> 往目标站点发送请求 --> 接收响应数据 --> 提取有用的数据 --> 保存到本地/数据库。
爬虫的过程:
1.发送请求(requests模块)
2.获取响应数据(服务器返回)
3.解析并提取数据(BeautifulSoup查找或者re正则)
4.保存数据
本实践中将会使用以下两个模块,首先对这两个模块简单了解以下:
request模块:
requests是python实现的简单易用的HTTP库,官网地址:http://cn.python-requests.org/zh_CN/latest/
requests.get(url)可以发送一个http get请求,返回服务器响应内容。
BeautifulSoup库:
BeautifulSoup 是一个可以从HTML或XML文件中提取数据的Python库。网址:https://beautifulsoup.readthedocs.io/zh_CN/v4.4.0/
BeautifulSoup支持Python标准库中的HTML解析器,还支持一些第三方的解析器,其中一个是 lxml。
BeautifulSoup(markup, "html.parser")或者BeautifulSoup(markup, "lxml"),推荐使用lxml作为解析器,因为效率更高。
数据爬取
一、爬取百度百科中《乘风破浪的姐姐》中所有参赛嘉宾信息,返回页面数据
爬取的是图中的表格信息:
import json
import re
import requests
import datetime
from bs4 import BeautifulSoup
import os
def crawl_wiki_data():
"""
爬取百度百科中《乘风破浪的姐姐》中嘉宾信息,返回html
"""
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'
}
url='https://baike.baidu.com/item/乘风破浪的姐姐'
try:
response = requests.get(url,headers=headers)
#将一段文档传入BeautifulSoup的构造方法,就能得到一个文档的对象, 可以传入一段字符串
soup = BeautifulSoup(response.text,'html.parser')
#返回所有的<table>所有标签
tables = soup.find_all('table')
crawl_table_title = "按姓氏首字母排序"
for table in tables:
#对当前节点前面的标签和字符串进行查找
table_titles = table.find_previous('div')
for title in table_titles:
if(crawl_table_title in title):
return table
except Exception as e:
print(e)
返回html文件。
二、对爬取的参赛嘉宾页面数据进行解析,并保存为JSON文件
def parse_wiki_data(table_html):
'''
解析得到选手信息,包括包括选手姓名和选手个人百度百科页面链接,存JSON文件,保存到work目录下
'''
bs = BeautifulSoup(str(table_html),'html.parser')
all_trs = bs.find_all('tr')
stars = []
for tr in all_trs:
all_tds = tr.find_all('td') #tr下面所有的td
for td in all_tds:
#star存储选手信息,包括选手姓名和选手个人百度百科页面链接
star = {
}
if td.find('a'):
#找选手名称和选手百度百科连接
if td.find_next('a'):
star["name"]=td.find_next('a').text
star['link'] = 'https://baike.baidu.com' + td.find_next('a').get('href')
elif td.find_next('div'):
star["name"]=td.find_next('div').find('a').text
star['link'] = 'https://baike.baidu.com' + td.find_next('div').find('a').get('href')
stars.append(star)
json_data = json.loads(str(stars).replace("\'","\""))
with open('work/' + 'stars.json', 'w', encoding='UTF-8') as f:
json.dump(json_data, f, ensure_ascii=False)
需要在代码文件目录中新建“work”文件夹:
三、爬取每个选手的百度百科页面的信息,并进行保存
- 这里可以查看网页源代码(F12),查看需要爬取的信息所处的html标签,不同网页使用的标签和属性都不同,要灵活变通。
- 如这里百度百科图片的爬取,有些选手的百科网页上的图片所在标签为类summary-pic,有的为类lemma-album,本文通过分支语句实现正确爬取。
def crawl_everyone_wiki_urls():
#爬取每个选手的百度百科图片,并保存
with open('work/' + 'stars.json', 'r', encoding='UTF-8') as file:
json_array = json.loads(file.read())
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'
}
star_infos = []
for star in json_array:
star_info = {
}
name = star['name']
link = star['link']
star_info['name'] = name
#向选手个人百度百科发送一个http get请求
response = requests.get(link,headers=headers)
#将一段文档传入BeautifulSoup的构造方法,就能得到一个文档的对象
bs = BeautifulSoup(response.text,'html.parser')
#获取选手的民族、星座、血型、体重等信息
base_info_div = bs.find('div',{
'class':'basic-info cmn-clearfix'})
dls = base_info_div.find_all('dl')
for dl in dls:
dts = dl.find_all('dt')
for dt in dts:
if "".join(str(dt.text).split()) ==