昨日内容回顾
-
requests模块发送post请求
requests.post(url,data={})
-
代码模拟登录(重要)
""" 编写爬虫的基本思路 先用浏览器正常操作 之后查找相应的目标数据及规律 最后使用代码爬取 """ 1.查找数据提交的地址 2.查找请求体数据格式 3.代码模拟发送数据 4.获取cookie数据用于身份认证 # 代码层面任何判断用户是否登录
-
json格式数据
json格式字符串数据使用的都是双引号 json格式数据能够打破语言限制 实现不同编程语言之间的数据交互 dumps 序列化 loads 反序列化 dump 序列化(文件) load 反序列化(文件)
-
获取较大数据
res = request.get(url,stream = True) for line in res.iter_content(): # 按行读取数据 pass
-
防爬措施及解决策略(重要)
1.检验是否是浏览器 请求头里面添加相应的键值对即可 2.检验当前请求来源 请求头里面添加相应的键值对即可 3.IP代理池 requests.get(url,proxies={}) 4.cookie代理池 requests.get(url,cookies={}) # 后续还会学习更多更加复杂的防爬措施
-
解析库之bs4模块
简单的理解为内部封装了正则表达式的用于快速帮你筛选数据的模块 pip3 install beautifulsoup4 pip3 install lxml # 对应的解析器 from bs4 import BeautifulSoup soup = BeautifulSoup('网页数据','lxml') soup.标签名 # 获取页面上从上往下第一个对应的标签 soup.标签名.attrs # 获取标签内部所有的属性 soup.标签名.text # 获取标签内部的文本数据 soup.find(name='标签名') # 获取页面上从上往下第一个对应的标签 soup.find_all(name='标签名') # 获取页面上所有对应的标签 """ 标签之间的关系 主要是通过是否在内部来决定 """
今日内容概要
- bs4模块查找标签详细操作
- 爬取红牛分公司数据
- 爬取天气数据
- 爬取链家二手房数据
- 更多实战案例(知识点直接在案例中讲解)
今日内容详细
bs4模块查找标签详细操作
# 四种过滤器
#1.1、字符串:即标签名
# print(soup.find_all('b'))
#1.2、正则表达式
# import re
# print(soup.find_all(re.compile('^b'))) #找出b开头的标签,结果有body和b标签
#1.3、列表:如果传入列表参数,Beautiful Soup会将与列表中任一元素匹配的内容返回.下面代码找到文档中所有<a>标签和<b>标签:
# print(soup.find_all(['a','b']))
#1.4、True:可以匹配任何值,下面代码查找到所有的tag,但是不会返回字符串节点
# print(soup.find_all(True))
# for tag in soup.find_all(True):
# print(tag.name) # for循环获取页面上所有的标签名称
find_all()
print(soup.find_all(name='a'))
# name后面放标签名称即可 name参数也可以省略 print(soup.find_all('a'))
print(soup.find_all(attrs={'id':'link1'})) # 查找属性中id=link1的标签
print(soup.find_all(attrs={'class':'title'})) # 查看属性中class=title的标签
print(soup.find_all(attrs={'id':'link1','class':'title'}))
# 也可以放多个键值对 是and关系
print(soup.find_all(id='link1')) # 也可以直接书写属性名和属性值
print(soup.find_all(class_='title'))
# 针对class不能直接书写 因为class是python的关键字
print(soup.find_all(name='a',class_='title'))
# 查看a标签 但是必须具有class=title的a标签
print(soup.find_all('a',text='Lacie'))
# 也可以根据标签内部的文本筛选标签 但是需要注意必须跟上其他的筛选条件
find与find_all用法一致 只不过find只找一个而已
css选择器
CSS选择器
1.标签选择器(通过标签名查找标签)
print(soup.select('a'))
2.id选择器(通过id值查找标签)
print(soup.select('#link1')) # 查找id=link1的标签
'''css选择器针对id属性统一使用#代替'''
3.class选择器(通过class值查找标签)
print(soup.select('.title')) # 查找class=title的标签
'''css选择器针对class属性统一使用.代替'''
print(soup.select('.story span'))
# 查找class=story标签内部所有的span标签
'''css选择器空格表示后代'''
print(soup.select('.story>span'))
# 查找class=story标签内部第一层级所有的span标签
'''css选择器大于号表示儿子'''
print(soup.select('#d1>.title'))
# 查找id=d1标签内部第一层级class=title的标签
print(soup.select('#d1>.title span'))
# 查找id=d1标签内部第一层级class=title的标签内部所有的span标签
爬取红牛分公司数据
import requests
import re
from bs4 import BeautifulSoup
1.尝试着直接朝地址发送请求 查看是否可以直接获取到相应的数据
res = requests.get(r'http://www.redbull.com.cn/about/branch') 'r取消转义'
print(res.status_code) # 200
print(res.text) # 有我们需要的内容
2.尝试着从html文本中筛选出我们需要的数据
# 方法一
'''正则表达式筛选'''
data = res.text
title_list = re.findall('<h2>(.*?)</h2>',data) '添加(),进行分组优先展示'
addr_list = re.findall("<p class='mapIco'>(.*?)</p>",data)
# 存在引号错误使用,需查看网页源码进行分别
email_list = re.findall("<p class='mailIco'>(.*?)</p>",data)
phone_list = re.findall("<p class='telIco'>(.*?)</p>",data)
# 打印展示
for i in range(len(title_list)):
print("""
公司名称:%s
公司地址:%s
公司邮箱:%s
公司电话:%s
"""%(title_list[i],addr_list[i],email_list[i],phone_list[i]))
# 写入excel
import pandas as pd
data_dict = {'公司名称':title_list,'公司地址':addr_list,'公司邮箱':email_list,'公司电话':phone_list}
# 将字典转换成DataFrame
df = pd.DataFrame(data_dict)
# 利用DataFrame内置方法直接导出到excel表格
df.to_excel(r'company.xlsx')
# 方法二
'''bs4模块筛选'''
soup = BeautifulSoup(res.text,'lxml')
# find_all select
print(soup.find_all(name='h2'))
# print(soup.select('h2'))
title_list = soup.select('h2') # [标签1、标签2...]
addr_list = soup.select('.mapIco') # soup.find_all('p',class_='mapIco')
email_list = soup.select('.mailIco')
phone_list = soup.select('.telIco')
for i in range(len(title_list)):
print("""
公司名称:%s
公司地址:%s
公司邮箱:%s
公司电话:%s
"""%(title_list[i].text,addr_list[i].text,email_list[i].text,phone_list[i].text))
'一个个筛选列表里的相应文本'
爬取链家二手房
地理位置如何确定? 通过地区拼音首字母
https://sh.lianjia.com/ershoufang/ 上海
https://bj.lianjia.com/ershoufang/ 北京
https://sz.lianjia.com/ershoufang/ 深圳
更加详细的区域如何确定? 通过区级完整拼音
https://sh.lianjia.com/ershoufang/jiading/ 嘉定
https://sh.lianjia.com/ershoufang/pudong/ 浦东
https://sh.lianjia.com/ershoufang/jinshan/ 金山
遇到多页数据的我们的处理思路是先研究单页之后再研究多页(很简单)
import requests
from bs4 import BeautifulSoup
# 1.直接发送get请求尝试是否可以获取到响应数据
res = requests.get('https://sh.lianjia.com/ershoufang/xuhui/')
# 2.研究页面布局筛选目标数据
soup = BeautifulSoup(res.text,'lxml')
# 研究发现所有的房屋信息都在一个固定的div里面
div_list = soup.find_all(name='div',attrs={'class':'info clear'})
# for循环获取每一个含有房屋所有信息的div标签并筛选出不同的部分
'''利用css选择器查找标签的时候 可以尽量写的精确一些 避免干扰'''
for div in div_list:
print(div.select('.title a')[0].text)
# print(div.select('.flood .positionInfo')[0].text)
# print(div.select('.address .houseInfo')[0].text)
# print(div.select('.followInfo')[0].text)
# print(div.select('.priceInfo .totalPrice')[0].text)
# print(div.select('.priceInfo .unitPrice')[0].text)
print("""
名称:%s
地址:%s
详情:%s
关注:%s
总价:%s
单价:%s
"""%(div.select('.title a')[0].text,
div.select('.flood .positionInfo')[0].text,
div.select('.address .houseInfo')[0].text,
div.select('.followInfo')[0].text,
div.select('.priceInfo .totalPrice')[0].text,
div.select('.priceInfo .unitPrice')[0].text
))
# 一行行获取地址,并将地址按分隔符'-',将地址分开
addr_l_list = soup.find_all(class_='positionInfo')
for l in addr_l_list:
l = l.text
print(l.split('-'))
# house_h_list = soup.find_all(class_='houseInfo')
# for h in house_h_list:
# print(h.text)
# 一行行获取详情,并将详情按照分隔符'|',将详情分开
att1_list = soup.find_all(class_='houseInfo')
for h in att1_list:
h = h.text
print(h.split('|'))
# 分开关注情况
att2_list = soup.find_all(class_='followInfo')
for f in att2_list:
f = f.text
print(f.split('/'))
# 分开总价
att3_list = soup.find_all(class_='totalPrice')
for t in att3_list:
t = t.text
print(t.split('|'))
作业
1.整理今日笔记
2.独立完成课上爬虫案例
分公司数据
二手房数据
3.在作业2的基础之上完成数据导出到excel表格
并且针对二手房数据完成多页爬取
4.自己查找其他感兴趣尝试爬取数据