day 2-bs4数据解析
1. requests设置浏览器信息
import requests
418现象: 网页对应的服务器做了身份验证,必须浏览器才能返回数据。如果不是浏览器发送的请求就会返回418
解决方案:设置请求的请求头中的用户信息为一个浏览器信息
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36'
}
response = requests.get('https://movie.douban.com/top250', headers=headers)
if response.status_code == 200:
print(response.text)
2. bs4基本用法
from bs4 import BeautifulSoup
1.创建网页对应的BeautifulSoup对象
BeautifulSoup(网页数据,解析器名称)
网页数据 - 需要解析的网页源代码
解析器 - lxml
html = open("data.html', encoding='utf-8').read()
soup = BeautifulSoup(html,'lxml')
2.获取标签
soup对象.select(css选择器) - 在整个网页中,获取css选择器选中的所有标签,返回值是列表,列表中的元素是标签对象
soup对象.select_one(css选择器) - 获取css选择器选中的标签中的第一个标签,返回值是标签对象
标签对象.select(css选择器) - 在指定标签中,获取css选择器选中的所有标签,返回值是列表,列表中的元素是标签对象
标签对象.select_one(css选择器) - 在指定标签中,获取css选择器选中的标签中的第一个标签,返回值是标签对象
result = soup.select('p')
print(result)
result = soup.select_one('p')
print(result)
# 获取所有商品的价格标签
result = soup.select('.goods_list .price')
print(result)
# 案例1:获取第一个商品的价格标签
# 方法1:
result = soup.select_one('.goods_list .price')
print(result)
# 方法2:
result = soup.select('.goods_list .price')[0]
print(result)
# 案例2:获取第二个商品的价格标签
# 方法1:
result = soup.select('.goods_list .price')[1]
print(result)
# 方法2
result = soup.select_one('.goods_list>li:nth-child(2)>.price')
print(result)
3.获取标签内容、获取标签属性
a = soup.select_one('div.c1>a')
1)获取标签内容: 标签对象.text
print(a.text)
2)获取标签属性:标签对象.attrs[属性名]
print(a.attrs['href'])
print(a.attrs['target'])
# 练习1:获取所有课程的名字
names_p = soup.select('.course_list .name')
course_names = [x.text for x in names_p]
print(course_names)
# 练习2:获取第二个课程的价格
price_p = soup.select_one('.course_list>li:nth-child(2)>.price')
print(price_p.text)
# 练习3:获取所有的课程以及对应的价格
# 方法1:
prices_p = soup.select('.course_list .price')
course_prices = [x.text for x in prices_p]
times_p = soup.select('.course_list span')
course_times = [x.text for x in times_p]
#
# # ['数据分析', '前端开发', 'java后端']
# # ['20000', '22000', '23000']
# # ['22周', '23周', '23周']
# #[{'name':'数据分析, 'price': '20000','time': '22周'}, {'name':'前端开发, 'price': '22000','time': '23周'}, ...]
result = map(lambda i1, i2, i3: {'name': i1, 'price': i2, 'time': i3}, course_names, course_prices, course_times)
print(list(result))
# 方法2:
courses_li = soup.select('.course_list>li')
all_course = []
for li in courses_li:
name = li.select_one('.name').text
price = li.select_one('.price').text
time = li.select_one('span').text
all_course.append({'name': name, 'price': price, 'time': time})
print(all_course)
3. bs4豆瓣电影解析
import requests
from bs4 import BeautifulSoup
import csv
from re import sub
# 1. 获取网络
def get_net_data(start):
headers = {
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36'
}
response = requests.get(f'https://movie.douban.com/top250?start={start}&filter=', headers=headers)
if response.status_code == 200:
return response.text
else:
return None
# 2. 解析数据
def analysis_data(html):
soup = BeautifulSoup(html, 'lxml')
all_li = soup.select('.grid_view>li') # 所有电影对应的li标签的列表
all_movie = []
for li in all_li:
name = li.select_one('.hd>a>span').text
info = li.select_one('.bd>p').text.strip().split('\n')[1].strip()
info = sub(r'\s+', '', info).split('/')
time = info[0]
country = info[1]
f_type = info[-1]
score = li.select_one('.rating_num').text
comment_count = li.select_one('.star>span:nth-child(4)').text[:-3]
all_movie.append({
'名称': name,
'评分': score,
'评论人数': comment_count,
'国家': country,
'上映时间': time,
'类型': f_type
})
with open('files/豆瓣电影.csv', 'a', encoding='utf-8', newline='') as f:
writer = csv.DictWriter(f, ['名称', '评分', '评论人数', '国家', '上映时间', '类型'])
if start == 0:
writer.writeheader()
writer.writerows(all_movie)
if __name__ == '__main__':
for start in range(0, 226, 25):
data = get_net_data(start)
analysis_data(data)
print('一页数据获取成功!', start//25)