爬虫练习和bs4使用

爬虫阶段训练和bs4使用

  • 菜场价格爬取
  • 爬虫解析库bs4
  • 红牛分公司爬取

菜场价格爬取

思路

1.查看页面加载方式,右键网络源代码
2.获取数据不在存在,此网站为js动态请求
3.在network中XHR,查找信息获取URL,确定请求方法
4.获取数据结果,选择需要的数据,发现list是我们需要的数据
5.分析数据,发现ID用于确定具体信息数据,一个组对应一个蔬菜
  结论:
  循环获取信息,发送post请求,就可以循环获取每个蔬菜的详情信息
6.查找目录数据信息与页数对应关系。
9.current参数用于控制页数,可通过for循环获取页数,循环输出个页面的数据
10.查看页面数为181417页设置循环,可以设置循环页数,以免服务器和电脑过载
'''
爬取数据时,最好设置一个时间间隔,避免服务器工作量增大,客服端IP被封
'''

代码

# 调用模块
import requests
import json
import os
# 判断是否存在蔬菜文件夹
if not os.path.exists(r'蔬菜'):
    # 创建蔬菜文件
    os.mkdir(r'蔬菜')
# 设置循环值,即页数
vert_page=int(input('请输入开始页码:'))
# 结束页码
end_page=int(input('请输入结束页码:'))
# 判断页码是否符合逻辑
if vert_page >= end_page:
    # 提示信息
    print('结束页码不能小于开始页码')
# 符合逻辑
else:
    # 设置循环
    while vert_page <= end_page:
        # 发送post请求
        res=requests.post("http://www.xinfadi.com.cn/getPriceData.html",
                          # 请求头
                          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"},
                          # 请求体
                          data={"limit": 20,
                                # 页码参数
                                "current": vert_page,
                                "pubDateStartTime":"",
                                "pubDateEndTime":"",
                                "prodPcatid":"",
                                "prodCatid":"",
                                "prodName":""}
                          )
        # 获取一页整体的蔬菜信息
        blist=res.json().get("list")
        # 循环获取每个信息
        for vert_id in blist:
            # 定义对应变量,蔬菜名
            cname=vert_id.get('prodName')
            # 定义对应变量,生产地
            cplace=vert_id.get('place')
            # 定义单位
            cinfo=vert_id.get('unitfo')
            #
            cavPrice=vert_id.get('avgPrice')
            # 获取信息
            print('菜名%s,产地%s,单位%s,品均价%s'%(cname,cplace,cinfo,cavPrice))
            # 见蔬菜信息写入文件
            with open(r'蔬菜\蔬菜%s.txt'%vert_id.get('prodName'), 'w',encoding="utf8") as f:
                # 以json格式,一行行写入
                json.dump(vert_id,f)
        # 增加页码
        vert_page+=1;

 

 

爬虫解析库bs4

bs4全名beautiful soup4

  可以从HTML和XML文件中提取数据的Python库,他能够通过个人喜欢的转换器实现惯用的文档导航,查找,修改文档的方式,bs会省数小时甚至数天的工作时间

模块下载

方法1:

pycharm终端界面或dos界面,如果速度慢,可以加-i改变网络地址

pip3 install beautifulsoup4 -i

方法2:

点击file>>>settings>>>项目名>>>interperter>>>加号>>>输入模块名>>>install

 

 配套解析器下载

  bs4模块也调用了其他解析器,不下载就无法使用,下载方式和上述模块相同

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>
"""

构造解析对象

语法:

语法:
soup =BeautifulSoup(目的变量名, '文件格式')

eg:
soup = BeautifulSoup(html_doc, 'lxml')

bs4内置方法

输出从上往下第一个a标签

# soup.标签名
print(soup.a)

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

print(soup.p.text)
print(soup.a.text)

 

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

print(soup.p.attrs)
print(soup.a.attrs)

 

 获取标签内部相应的属性的value值

print(soup.p.attrs.get('fog'))
print(soup.a.attrs.get('href'))

 

 简写省略attrs参数

print(soup.a.get('href'))

 

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

语法:
    soup.标签名.children
eg:
# 需要循环取值才可以拿到
for i in soup.p.children: print(i)

 

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

语法:
soup.标签名.contents
eg:
    print(soup.p.contents)

 

 获取标签所有的父标签

语法:
    soup.标签名.parent
eg:
    print(soup.p.parent)

获取标签所有的父标签(迭代器)

语法:
    soup.标签名.parents
eg:
    # 返回为迭代器
    for i in soup.p.parents:
    print(i)

核心操作

1.find方法

缺点:只能找到符合条件的第一个,返回结果是一个标签对象

语法:
    soup.find(name='标签名',attrs={'属性':'属性名'})
eg:    
    # 查找a标签   默认只找符合条件的第一个
    print(soup.find(name='a'))

# 找id为link2的a标签  默认只找符合条件的第一个
print(soup.find(name='a',id='link2'))

# 为了解决关键字冲突 会加下划线
print(soup.find(name='p',class_='title'))

# 使用attrs参数,可以避免关键字冲突
print(soup.find(name='a', attrs={'id': 'link3','class':'sister'}))

# 没有name参数,也可以查找符合后续条件的标签
print(soup.find(attrs={'id': 'link3','class':'sister'}))

 2.find_all方法

优点:查找所有符合条件的标签 ,返回结果是一个列表

语法:
name参数可省略,find_all方法与find一致    
soup.findall('标签名')
eg:
  # 查找所有a标签
print(soup.find_all('a'))

# 查找所有clas为sister的
print(soup.find_all(attrs={'class':'sister'}))

3.select方法

需要使用CSS选择器,返回一个列表

标签选择器

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

eg:

# 查找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'))

# 查找class等于story标签内部所有id为link的标签
print(soup.select('.story #link1'))

#也可以嵌套select,但其实没必要,一条select就可以了
print(soup.select('.story')[0].select('#link1'))

 

爬取红牛分公司数据

要求:获取红牛所有分公司详细数据(名称 地址 邮箱 电话)

思路:

1.判断数据加载方式,打开网络源地址,查找数据,发现为直接加载

2.进入network,查找url地址、请求方式或请求头等信息
3.执行代码筛选

代码

# 调用模块
import requests
from bs4 import BeautifulSoup
# 请求数据
res=requests.get('http://www.redbull.com.cn/about/branch')
# 构造解析对象
soup =BeautifulSoup(res.text,'lxml')
# 获取公司名
h2_list=soup.find_all('h2')
# 生成公司名列表
namelist=[title.text for title in h2_list]
# 获取具体地址
p_add=soup.find_all(attrs={'class':'mapIco'})
# 生成地址列表
addr_list = [tag.text for tag in p_add]
# 获取邮箱
p_mail=soup.select('.mailIco')
# 生成邮箱列表
email_list = [tag.text for tag in p_mail]
# 获取电话
p_phone=soup.select('.telIco')
# # 生成电话列表
phone_list = [tag.text for tag in p_phone]
# 循环输出数,以表长为索引值
for i in range(len(h2_list)):
    print('''
    公司名称:%s
    公司地址:%s
    公司邮箱:%s
    公司电话:%s 
    '''%(addr_list[i],addr_list[i], email_list[i], phone_list[i]))

返回目录

posted @ 2021-09-20 20:56  微纯册  阅读(124)  评论(0编辑  收藏  举报