一周内容回顾(9.13-9.18)

day01

  • 常见收集数据网站
  • 爬虫及分类
  • 网页组成

常见收集数据网站

免费类(国内)

# 百度指数:https://index.baidu.com/v2/index.html#/
是以百度海量网民行为数据为基础的数据分析平台
# 新浪指数:https://data.weibo.com/index
是对提及量、阅读量、互动量加权得出的综合指数,更加全面的体现关键词在微博上的热度情况
# 国家数据:http://www.gov.cn/shuju/index.htm
中国各项有关政治类的数据都在其中

免费类(国外)

# 世界银行:https://data.worldbank.org.cn/
是联合国的一个专门机构,上面的数据基本都是有关银行,金融,贷款等
# 纳斯达克:https://www.nasdaq.com/zh/market-activity
是美国的一个电子证券交易机构,里面的数据基本都是与股票相关
# 联合国:http://data.un.org/
里面是有关自由贸易,出入境人员记录等数据

付费类(国内)

# 艾瑞咨询:https://www.iresearch.com.cn/  
是解决商业决策问题的专业第三方机构

 付费类(国际)

# 埃森哲:https://www.accenture.com/cn-zh 
为客户提供战略、咨询、数字、技术和运营服务及解决方案
# 麦肯锡:https://www.mckinsey.com.cn/
帮助领先的企业机构实现显著、持久的经营业绩改善,打造能够吸引、培育和激励杰出人才的优秀组织机构

付费类(第三方平台)

# 数据堂:https://www.datatang.com/  
数据堂专注于人工智能数据服务,致力于为全球人工智能企业提供数据获取及数据产品服务
# 贵阳大数据:http://gbdex.bdgstore.cn/
是一个面向全国提供数据交易服务的创新型交易场所

网络爬虫的理论

互联网

互联网是由网络设备(网线,路由器,交换机,防火墙等等)和一台台计算机连接而成,像一张网一样

互联网建立的核心目的

互联网的核心价值在于数据的共享/传递

上网

由用户端计算机发送请求给目标计算机,将目标计算机的数据下载到本地的过程

爬虫

跳过代码模拟网络请求获取数据并解析数据最后保存

 爬虫的价值

如果我们把互联网比作一张大的蜘蛛网,那一台计算机上的数据便是蜘蛛网上的一个猎物,而爬虫程序就是一只小蜘蛛,沿着蜘蛛网抓取自己想要的猎物/数据

爬虫的分类

通用爬虫

搜索引擎用的爬虫系统,类似于百度
尽可能把互联网所有的网页下载放到本地服务器形成备份
再对这些网页做相关处理最后给用户提供检索结果

搜索引擎如何获取一个网站URL

1.主动向搜索引擎提交网址
            网址收录:https://ziyuan.baidu.com/site/index
2.在其他网址设置网站外链
3.与DNS服务商合作(DNS即域名解析技术)  
            简便获取ip地址:ping URL -t

robots协议

协议内会指明可以爬取网页的部分数据

百度快照

每个被收录的网页,在百度上都存有一个纯文本的备份,称为百度快照

 通用爬虫工作流程

爬取网页>>>存储数据>>>内容处理>>>提供检索及排名服务

排名:
1.PageRank值
根据网站的流量统计
2.竞价排名
金钱交易过后晋升上去

 聚焦爬虫

爬虫程序员写的针对指定内容的爬虫

网页组成

HTML:超文本标记语言

# 浏览器可以展示出来的界面都是由HTML构成的
eg:
    天猫官网 

 前端与后端

前端
    任何与用户直接打交道的操作界面都可以称之为"前端"
后端
    程序员编写的运行在程序内部不直接与用户打交道的程序代码
        一般都是指代程序员编写的代码

 前端三剑客

HTML              网页的骨架
CSS                网页的样式
JavaScript(JS)     网页的动态效果    

HTML基本组成

# 网页文件一般都是以.html结尾

# HTML语法结构
    <html>
        <head>书写的一般都是给浏览器看的</head>
        <body>书写的就是浏览器要展示给用户看的</body>
    </html>
  

head内常见标签

title      定义网页标题
style      内部直接书写css代码
link       引入外部css文件
script     内部可以直接书写js代码也可以引入外部js文件
meta        定义网页源信息

body内常见标签

html标签分类

双标签(有头有尾)
  <a></a>

单标签(自闭和) <img/>

基本标签

h标签

<h1>This is a heading</h1>
<h2>This is a heading</h2>
<h3>This is a heading</h3>
<h4>This is a heading</h4>
<h5>This is a heading</h5>
<h6>This is a heading</h6>

 b/i/u/s标签

<b>加粗</b>
<i>斜体</i>
<u>下划线</u>
<s>删除线</s>

P标签

<p>吃葡萄不吐葡萄皮,不吃葡萄倒吐葡萄皮</p>
<p>吃葡萄不吐葡萄皮,不吃葡萄倒吐葡萄皮</p>
<p>吃葡萄不吐葡萄皮,不吃葡萄倒吐葡萄皮</p> 

br标签

<p>吃葡萄不吐葡萄皮,<br />不吃葡萄倒吐葡萄皮</p>

hr标签

<p>This is a paragraph<p>
<hr />

day02

  • 特殊符号

  • 常用标签

  • 列表标签

  • 表格标签

  • 表单标签

  • 正则表达式

特殊符号

空格    &nbsp;
>      &gt;
<      &lt;
&      &amp;
¥      &yen;
版权    &copy;
注册    &reg;

 常用标签

<a href="网址">链接标签</a>
    href参数后面写网址 用户点击即可跳转到该网页
 
<img src="111.png" alt="">图片标签
    src参数后面写图片的地址 网络或本地都可以
 
<div>页面布局标签</div>
    内部可以无限制的嵌套任意标签
  
<span>页面文本标签</span>
    是所有网页中涉及到文字可能会出现的标签

列表标签

"""在网页上看似有规则排列的横向或者竖向的内容基本都是用列表标签完成的"""
<ul>
    <li>001</li>
    <li>002</li>
    <li>003</li>
    <li>004</li>
    <li>005</li>
</ul>

 表格标签

<table>
    <thead>
        <tr>
            <th>序号</th>      
            <th>姓名</th>
            <th>年龄</th>
        </tr>                  
    </thead>                 
    <tbody>
        <tr>
            <td>1</td>        
            <td>ben</td>
            <td>123</td>
        </tr>
    </tbody>                 
</table>

 

 表单标签

"""涉及到用户数据的获取一般都需要使用表单标签"""
input标签
type       参数
text       普通文本
password   密文展示
email      邮箱格式
date       日期格式
radio        单选
checkbox     多选
file         文件
submit      提交按钮
reset       重置按钮
button      普通按钮  

select标签
  option子标签
textarea标签   获取大量文本

 标签特性

<a id='' class=''></a>
上述id、class等都称之为a标签的属性

标签两大核心属性

id    # 单独查找某个人
类似于标签的身份证号码 用于唯一标识标签
在同一个html文档中id不能重复
class  # 批量查找一群人
类似于标签的种群(类别) 用于区分不同的类
在用一个html文档中class值可以重复 表示属于同一个类别

"""标签还可以自定义任意的属性"""
<a username='jason' pwd=123></a>

 标签之间的关系描述

<div>只要是div内部的标签都可以称之为是div的后代
    <a>上一级div的儿子</a>
    <p>上一级div的儿
        <span>上一级p的儿子,上上一级div的孙子</span>
    </p>
    <div>上一级div的儿
        <a>上一级div的儿子,上上一级div的孙子</a>
    </div>
    <span>上一级div的儿子</span>
</div> 

正则表达式

python代码实现数据校验

# 1.获取用户手机号
        phone = input('phone num>>>:').strip()
        # 2.先判断长度是否是11位
        if len(phone) == 11:
            # 3.再判断是否是纯数字
            if phone.isdigit():
                # 4.最后判断开头是否是13 14 15 18
                if phone.startswith('13') or phone.startswith('14') or phone.startswith('15') or phone.startswith('18'):
                    print('是一个合法的手机号')
                else:
                    print('手机号格式错误')
            else:
                print('手机号必须是纯数字')
        else:
            print('手机号必须是11位')
View Code

正则表达式校验

import re
        phone_number = input('please input your phone number : ')
        if re.match('^(13|14|15|18)[0-9]{9}$',phone_number):
                print('是合法的手机号码')
        else:
                print('不是合法的手机号码')
# 使用正则表达式可以极大的简化数据筛选和校验的步骤
View Code

 

正则表达式之字符组

[0123456789]  匹配0到9之间的任意一个数字包括首尾
[0-9]         简写:匹配0到9之间的任意一个数字包括首尾
[a-z]  匹配小写字母a到z之间的任意一个字母包括首尾
[A-Z]  匹配大写字母A到Z之间的任意一个字母包括首尾

[0-9a-zA-Z] 匹配数字或者小写字母或者大写字母

总结

字符组在匹配内容的时候是单个单个字符挨个匹配

正则表达式之符号

   .         匹配除换行符以外的任意字符
    \d       匹配数字
    ^        匹配字符串的开始
    $        匹配字符串的结尾
    a|b      匹配字符a或字符b
    ()       给正则表达式分组 本身没有任何意义
    [...]    匹配字符组中的字符
    [^...]   匹配除了字符组中字符的所有字符(取反)

正则表达式之量词

# 跟在正则表达式的后面可以一次性匹配多个字符
'''量词必须跟在正则表达式后面 不能单独出现使用'''
*        重复零次或更多次
+        重复一次或更多次
?        重复零次或一次
{n}      重复n次
{n,}     重复n次或更多次
{n,m}    重复n到m次

贪婪匹配

右侧尽可能多的匹配直到根据相关条件才停止

 非贪婪匹配

将贪婪匹配变成非贪婪匹配只需要在量词后面加一个问号即可

 取消转义

\n        匹配的是换行符
\\n       匹配的是\n
\\\\n     匹配的是\\n

day03

  • re模块
  • 爬虫模块之requests
  • 网络请求的方式
  • requests模块演示

re模块基本用法

演示准备


findall(正则,文本数据)
    在匹配的时候是全局匹配不会因为匹配到一个就停止 
    返回的结果是一个列表 内部包含正则匹配到的所有的内容
finditer(正则,文本数据)
    返回的结果是一个迭代器,只有主动索要才会产生数据,否则永远只占一块空间,节省了内存空间
# 匹配到一个符号条件的数据就结束
search()
# 只能从头开始匹配 头部不符合直接停止
match()

 分组优先级

优先展示

"""
findall分组优先展示,会优先展示括号内正则表达式匹配到的内容
"""

ret = re.findall('www.(baidu).com', 'www.baidu.com')
print(ret)

 取消分组优先展示

# 在括号内容前面加上问号和冒号

ret = re.findall('www.(?:baidu).com', 'www.baidu.com')
print(ret)

爬虫模块之requests

# 作用
可以模拟浏览器发送网络请求获取数据

# 如何下载
在pycharm终端里敲写pip3 install requests
或直接快捷键操作即可

# 如何导入
import requests 

 网络请求方法

get请求

朝服务器索要数据

eg:浏览器地址栏输入百度网址回车其实就是在发送get请求朝百度服务器索要百度首页

补充

# get请求也可以携带额外的数据
但是数据量有限制最多2~4KB,并且是直接写在网址的后面
        
url?xxx=yyy&zzz=bbb

 post请求

朝服务器提交数据

eg:用户注册登录需要输入用户名和密码之后点击按钮发送post请求将数据提交给远程服务器

补充

post请求也可以携带额外的数据 并且数据大小没有限制
敏感性的数据都是由post请求携带
而数据放在请求体中

HTTP协议

规定了浏览器与服务端之间数据交互的方式

四大特性

1.基于请求响应
2.基于TCP、IP作用于应用层之上的协议
3.无状态
不保存客户端的状态
4.无连接
限制每次连接只处理一个请求
服务器处理完客户的请求,并收到客户的应答后,即断开连接

数据请求格式

请求数据格式

        请求首行(请求方法 地址...)
        请求头(一大堆K:V键值对)
        # 此处换行一定不能忘
        请求体(get请求没有请求体,post请求有,里面是敏感数据)

响应数据格式

        响应首行(响应状态码 协议版本...)
        响应头(一大堆K:V键值对)
        # 此处换行一定不能忘
        响应体(一般都是给浏览器展示给用户看的数据)    

响应状态码

用简单的数字来表示一串中文意思类似于暗号

举例

1XX——————服务端已经成功接收到了用户的数据正在处理 用户可以继续提交或者等待
2XX——————200 == OK请求成功服务端发送了响应
3XX——————重定向(原本想访问A页面但是内部自动跳到了B页面)
4XX——————403请求不符合条件    404请求资源不存在
5XX——————服务器内部错误

 自定义响应状态码

因为HTTP的状态码太少不够用
所以有些公司创建了自定义响应状态码
eg:        
10001————xxx    
10002————yyy

requests模块基本使用

发送网络请求
    import requests
    requests.get(url)  # 发送get请求
    requests.post(url)  # 发送post请求

获取响应状态码

# print(res.status_code)

指定字符编码

# res.encoding = 'utf8'
# print(res.text)  # 获取网页字符串数据

获取bytes类型的数据

print(res.content)

获取页面

import requests

res = requests.get('https://www.baidu.com/')
with open(r'baidu1.html', 'wb') as f:
    f.write(res.content)

携带参数的get请求

requests.get(url,params={})

如何携带请求头数据

requests.get(url,headers={})

代码版搜索引擎

import requests


headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36'
}
keyword = input('请输入你想搜索的数据>>>:').strip()
res = requests.get('https://www.baidu.com/s',
                    params={'wd':keyword},
                    headers=headers
                   )
with open(r'zzx.html','wb') as f:
    f.write(res.content)
View Code

防爬措施

校验当前请求是否是浏览器发出的
需请求头里面的User-Agent键值对
只要请求里面含有该键值对,就表示自己是个浏览器,没有则不是

 

day04

  • cookie与session
  • 代码模拟用户登录
  • json格式数据
  • ip代理池
  • cookie代理池

cookie与session

cookie

cookie:保存在客户端浏览器上面的键值对数据

用户第一次登录成功之后,浏览器会保存用户名和密码
之后访问网站都会自动带着该用户名和密码

 session

session:保存在服务端上面的用户相关的数据

用户第一次登录成功之后,服务端会返回给客户端一个随机字符串
客户端浏览器保存该随机字符串之后访问网站都带着该随机字符串

两者关系

session需要依赖cookie
只要是涉及到用户登录都需要使用到cookie

 PS:浏览器也可以拒绝保存数据

代码模拟用户登录

 步骤一

研究登录数据提交给后端的url地址

# 登录地址:http://www.aa7a.cn/user.php

步骤二

研究登录post请求携带的请求体数据格式
浏览器network选项中,请求体对应的关键字是Form Data

 步骤三

模拟发送post请求

获取cookie数据

res1 = requests.get('http://www.aa7a.cn/',
                    cookies=user_cookie
                    )
if 'xxxxxxxxx@qq.com' in res1.text:
    print('登录身份访问')
else:
    print('cookie存在错误')
View Code

 使用cookie访问网站

res1 = requests.get('http://www.aa7a.cn/',
                    cookies=user_cookie
                    )
if 'xxxxxxxxx@qq.com' in res1.text:
    print('登录身份访问')
else:
    print('cookie存在错误')
View Code

 

 获取大数据

# stream参数
比如下载视频时,如果视频有100G
用response.content然后一下子写到文件中是不合理的
所以一点I一点取

json格式

在网络爬虫领域,其实内部有很多数据都是采用的json格式
# 前后端数据交互一般使用的都是json格式

IP代理池

# 代理设置:先发送请求给代理,然后由代理帮忙发送

对于封IP的网站,需要很多的代理IP,而每个卖代理IP的网站也提供了免费IP,IP代理池由此而来

Cookie代理池

有很多网站针对客户端的cookie也存在防爬措施
    eg:比如一分钟之内同一个cookie访问该网站的次数不能超过30次超过了就封禁该cookie


如何解决?
# cookie代理池
里面有很多cookie每次访问从中随机挑选一个

 

day05

  • 数据的加载方式
  • 爬取天气数据
  • 爬取百度翻译
  • 爬取药品许可证
  • 爬取北京新发地蔬菜价格表

数据的加载方式

1.常见的加载方式

朝服务器发请求 页面数据直接全部返回并加载

2.内部js代码请求

先加载一个页面的框架,之后再朝各项数据的网址发送请求获取数据

如何验证数据是直接加载还是其他方式

浏览器空白处鼠标右键,点击查看网页源码,在源码界面搜索对应的数据
如果能收到就表示该数据是直接加载的

 如何查找关键性的数据来源

需要借助于浏览器的network监测核对内部请求
请求的数据一般都是json格式

 爬取天气数据

思路

1.拿到页面之后先分析数据加载方式
2.发现历史数据并不是直接加载的
3.查找到可疑的网址并查看请求方式
如果是get请求那么可以直接拷贝网址在浏览器地址访问
4.将请求获得的数据稍作分析
网站:https://www.bejson.com/
5.利用requests模块朝发现的地址发送get请求获取json数据
6.可以研究历史天气数据的url找规律,即可爬取指定月份的数据

代码演示

import requests


res = requests.get('http://tianqi.2345.com/Pc/GetHistory?areaInfo%5BareaId%5D=60010&areaInfo%5BareaType%5D=2&date%5Byear%5D=2021&date%5Bmonth%5D=8')
real_data_html = res.json().get('data')
print(real_data_html)
View Code

 

 爬取百度翻译

思路

1.在查找单词的时候页面是在动态变化的
2.并且针对单词的详细翻译结果数据是动态请求获取的
3.打开network之后输入英文查看内部请求变化
发现sug请求频率固定且较高
4.研究sug请求发现每次输入的单词都会朝固定的一个网址发送post请求
并且请求体携带了改单词数据

代码演示

import requests

keyword = input('请输入你想要翻译的单词>>>:')
res = requests.post('https://fanyi.baidu.com/sug',
                    data={'kw':keyword}
                    )
data_list = res.json().get('data')
for d in data_list:
    print(d)
View Code

 爬取药品许可证

思路

# 需求:爬取药品企业生产许可证详细信息
1.先明确是否需要爬取页面数据 如果需要则先查看数据的加载方式
2.通过network查看得知数据是动态加载的 网页地址只会加载一个外壳
3.通过network点击fetch/xhr筛选动态获取的地址和请求方式
4.利用requests模块发送相应请求获取数据 之后再分析
5.利用浏览器点击详情页查找关键数据
6.由于我们需要爬取详情页的数据所以要验证数据的加载方式
7.详情页核心数据也是动态加载的 发现是post请求并携带了一个id参数
    id: 911d4f256300476abb78012427d38c9d
8.通过比对得知id数据与第一次爬取的公司简介里面的id一致 从而得出结论
    循环获取格式简介id 然后发送post请求 获取每个公司的详细数据

 代码演示

import requests


res = requests.post('http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsList',
                    data={
                        "on": "true",
                        "page": 1,
                        "pageSize": 15,
                        "productName":'',
                        "conditionType": 1,
                        "applyname":'',
                        "applysn": ''
                    }
                    )
# data_dict = res.json()
# data_list = data_dict.get('list')
# 上述两步合成一步
data_list = res.json().get('list')

# 循环获取格式id值
for d in data_list:
    # 字段取值 获取id值
    ID = d.get("ID")
    # 发送网络请求
    res1 = requests.post('http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsById',
                         data={'id':ID}
                         )
    # 获取数据结果
    data_dict = res1.json()
    print(data_dict)
View Code

 

 多页数据如何获取与如何存储到文件中

思路

1.先点击页码查看url的变化
如果数据变化url不变 那么数据肯定是动态加载的
如果数据变化url也变 那么数据可能是直接加载也可能是动态
2.针对上述案例 数据是动态加载 所以需要研究每一次点击页码内部请求
3.研究请求体参数得知数据页由page控制 
4.写一个for循环即可
5.并将数据写入文件存储起来

 代码演示

import os
import requests
import json



if not os.path.exists(r'company_info'):
    os.mkdir(r'company_info')
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36'}


url1 = 'http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsList'
for p in range(1,381):
    res1 = requests.post(url1,
                    headers=headers,
                     data={
                         'on': 'true',
                         'page': p,
                         'pageSize': 15,
                         'productName': '',
                         'conditionType': 1,
                         'applyname': '',
                         'applysn': ''
                     }
                     )
    com_list = res1.json().get('list')
    for i in com_list:
        id = i.get('ID')
        url2 = 'http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsById'
        res2 = requests.post(url2,
                             headers=headers,
                             data={'id': id}
                             )
        com_detail = res2.json()
        name = com_detail.get('epsName')
        info_add = os.path.join(r'company_info', name)
        with open(info_add, 'w', encoding='utf8') as f:
            json.dump(com_detail, f)
View Code

day06

  • 爬虫题讲解
  • bs4模块
  • 爬取红牛分公司数据

 

爬取北京新发地蔬菜相关数据

思想

1.明确题目需求,获取页面上某一块区域内部的核心数据
2.先查看核心数据的加载方式
3.发现数据并不在网页源码上,说明是内部动态加载的
4.通过network查看发现内部发送了一个post请求
5.post请求最为独特的就是请求体数据,所以需要研究一下

代码演示

import requests
import time

def get_price_data(n):
    res = requests.post('http://www.xinfadi.com.cn/getPriceData.html',
                        data={
                            "limit": '',
                            "current": n,
                            "pubDateStartTime": '',
                            "pubDateEndTime": '',
                            "prodPcatid": '',
                            "prodCatid": '',
                            "prodName": '',
                        }
                        )
    data_list = res.json().get('list')
    for d in data_list:
        pro_name = d.get('prodName')
        low_price = d.get('lowPrice')
        high_price = d.get('highPrice')
        avg_price = d.get('avgPrice')
        pub_date = d.get('pubDate')
        source_place = d.get('place')
        print("""
        蔬菜名称:%s
        最低价:%s
        最高价:%s
        平均价:%s
        上市时间:%s
        原产地:%s
        """ % (pro_name, low_price, high_price, avg_price, pub_date, source_place))
        time.sleep(1)


"""涉及到多页数据爬取的时候 最好不要太频繁 可以自己主动设置延迟"""
for i in range(1, 5):
    time.sleep(1)
    get_price_data(i)
View Code

爬虫解析库之bs4模块

全名:Beautiful Soup4
是一个可以从HTML或XML文件中提取数据的Python库
它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式
Beautiful Soup会帮你节省数小时甚至数天的工作时间

模块与配套解析器下载

# pip3 install beautifulsoup4

# pip3 install lxml

 bs4模块基本使用

演示准备

from bs4 import BeautifulSoup

# 构造一个网页数据
html_doc = """
<html>
    <head>
        <title>The Dormouse's story</title>
    </head>
    <body>
        <p class="title">
            <b>The Dormouse's story</b>
        </p>
        
        <p class="story">Once upon a time there were three little sisters; and their names were
        <a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>
        <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a>
        <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>
        and they lived at the bottom of a well.</p>
        
        <p class="story">...</p>
    </body>
</html>
"""
View Code

 

如何筛选

# 1.构造一个bs4解析器对象
soup = BeautifulSoup(html_doc, 'lxml')

# 2.利用对象的内置方法完成一系列操作
'''必须要掌握'''
print(soup.a)  # 从上往下的第一个a标签  soup.标签名称

 获取标签内部的文本 包含内部所有的后代标签文本

print(soup.p.text) 

 获取标签内部所有的属性  字典数据类型

print(soup.a.attrs)

 获取指定标签内的链接网址

print(soup.a.attrs.get('href'))
print(soup.a.get('href'))  # 可以简写 省略attrs参数

 获取标签内部所有的子标签 

print(soup.p.children)

 获取标签内部所有的元素

print(soup.p.contents)

 获取标签的父标签

 print(soup.p.parent)

 获取标签的所有祖先标签

 print(soup.p.parents)

 bs4核心操作

1.find方法

# 缺陷:只能找符合条件的第一个  该方法的返回结果是一个标签对象

查找指定标签名的标签 默认只找符合条件的第一个

print(soup.find(name='a'))  

查找具有某个特定属性的标签 默认只找符合条件的第一个

print(soup.find(name='a',id='link2'))  

为了解决关键字冲突 会加下划线区分

print(soup.find(name='p', class_='title'))

使用attrs参数 直接避免冲突

print(soup.find(name='p', attrs={'class': 'title'}))
print(soup.find(name='a', attrs={'id': 'link3'}))

class属性查找属于成员运算

print(soup.find(name='a', attrs={'class': 'c1'}))  

name参数不写则表示查找所有符合后续条件的标签

print(soup.find(attrs={'class': 'c1'}))

2.find_all方法

# 优势:查找所有符合条件的标签  该方法的返回结果是一个列表

name字段可以省略 查找的结果是一个列表

print(soup.find_all('a')) 

3.select方法

# 需要使用css选择器  该方法的返回结果是一个列表

演示准备

"""
<p></p>
<div>
    <a></a>
    <p>
        <a></a>
    </p>
    <div><p></p></div>
</div>
<p></p>
<p></p>

"""
View Code

选择器分类

1.标签选择器
    直接书写标签名即可
2.id选择器
    #d1  相当于写了 id='d1'
3.class选择器
    .c1  相当于写了 class=c1
4.儿子选择器(大于号)  选择器可以混合使用
     div>p  查找div标签内部所有的儿子p
5.后代选择器(空格)    选择器可以混合使用
    div p  查找div标签内部所有的后代p

查找class含有title的标签

print(soup.select('.title'))

查看class含有sister标签内部所有的后代span

print(soup.select('.sister span'))

查找id等于link1的标签

print(soup.select('#link1'))

查找id等于link1标签内部所有的后代span

print(soup.select('#link1 span'))

查找id等于list-2标签内部所有class为element的标签

print(soup.select('#list-2 .element'))

可以一直select,但其实一条select即可

print(soup.select('#list-2')[0].select('.element')) 

爬取红牛分公司数据

需求:获取红牛所有分公司详细数据(名称 地址 邮箱 电话)
    
1.查找数据加载方式 得知是直接加载的
2.朝该网页发送请求获取页面数据之后筛选即可

代码演示

import requests
from bs4 import BeautifulSoup

# 1.发送get请求获取页面内容
res = requests.get('http://www.redbull.com.cn/about/branch')
# 2.解析页面数据
soup = BeautifulSoup(res.text, 'lxml')
# 3.研究标签特性 精确查找
# 分公司名称数据
h2_tag_list = soup.find_all('h2')  # 查找到所有的h2标签对象
# for tag in h2_tag_list:
# print(tag.text)
# 使用列表生成式
title_list = [tag.text for tag in h2_tag_list]

# 分公司地址数据
p1_tag_list = soup.find_all(name='p', attrs={'class': 'mapIco'})
# for tag in p_tag_list:
#     print(tag.text)
# 使用列表生成式
addr_list = [tag.text for tag in p1_tag_list]

# 分公司邮箱数据
p2_tag_list = soup.find_all(name='p', attrs={'class': 'mailIco'})
# for tag in p2_tag_list:
#     print(tag.text)
email_list = [tag.text for tag in p2_tag_list]

# 分公司电话数据
p3_tag_list = soup.find_all(name='p', attrs={'class': 'telIco'})
# for tag in p3_tag_list:
#     print(tag.text)
phone_list = [tag.text for tag in p3_tag_list]

for i in range(len(title_list)):
    print("""
    公司名称:%s
    公司地址:%s
    公司邮箱:%s
    公司电话:%s 
    """ % (title_list[i], addr_list[i], email_list[i], phone_list[i]))
View Code

 

 

 

 

 

 

 

posted @ 2021-09-21 14:08  陌若安然  阅读(70)  评论(0)    收藏  举报