python爬虫BeautifulSoup实战练习

标签: python  python  数据分析

python爬虫BeautifulSoup实战练习,爬取价格并显示价格分布曲线

知识点介绍

涉及到的库如下:
requests库用于网页访问
bs4的BeautifulSoup进行网页解析
lxml第三方网页解析库,也可以使用python自带html.parser
re正则表达式用于查找提取字符
matplotlib.pyplot用于绘图
numpy用于辅助绘图处理对应数据

中途问题注意:使用CSS选择器选择获取了元素路径,但是带入BeautifulSoup的select方法中后始终获取不到数据,核对发现request获取的网页源码和浏览器获取的不一样,会导致CSS选择器选择的路径不正确,需要手工核对。

效果展示

在这里插入图片描述在这里插入图片描述

源代码

import requests
from bs4 import BeautifulSoup
import lxml
import re
import matplotlib.pyplot as plt
import numpy as np

def GetFruitInfo(pageCnt=3):
    retInfo=[]
    #来源地址,某些网站不指定来源地址不允许访问
    my_referer = r'https://www.lvguo.net/baojia/area/7000/'
    #需要提取信息的多个页面,用for循环生成
    urlList = ["https://www.lvguo.net/baojia/area/7006/"]
    for i in range(2,pageCnt+1):
        urlList.append("https://www.lvguo.net/baojia/area/7006/"+"t{0}".format(i))
    #print(urlList)
    for url in urlList:
        #url="https://www.lvguo.net/baojia/area/7006/t3"
        #调用requests的get方法获取网页源代码
        webData = requests.get(url,headers={'referer' : my_referer}).text
        #print(webData)
        #建立BeautifulSoup解析网页,这里调用的是python自带的解析器"html.parser",也可以用第三方的解析器"lxml"
        soup = BeautifulSoup(webData,"html.parser")
        #调用select方法并指定元素,用浏览器CSS选择器确定
        list=soup.select(".bjtbl > tr")
        for info in list[2:]:
            #获悉信息ID
            #查找第0个td标签的属性,提取出来
            infoId=info.select("td")[0].attrs["title"]
            #获取时间
            #调用find_all配合正则表达式查找具有title标题的标签,提取内容
            infoTime=info.find_all(title=re.compile(".*"))[0].get_text()
            #获取地址
            # 查找第1个td标签的子标签的文本
            infoAddress = info.select("td")[1].a.get_text()
            #获取类型
            infoType = info.select("td")[2].a.get_text()
            #获取价格
            infoPrice = info.select("td")[3].p.b.get_text()
            #获取联系人
            infoContact = info.select("td")[4].a.get_text()
            #print(infoId,infoTime,infoAddress,infoType,infoPrice+"元/斤",infoContact)
            retInfo.append([infoId,infoTime,infoAddress,infoType,infoPrice,infoContact])
    #返回提取的信息列表
    return retInfo

#从提取的信息列别筛选出对应的水果价格并形成列表
def FruitPriceInfo(fruitInfo):
    retInfo=[]
    #获取水果list
    fruitList = []
    for item in fruitInfo:
        if item[3] not in fruitList:
            fruitList.append(item[3])
    #print(fruitList)
    # 获取人list
    contactList = []
    for item in fruitInfo:
        if item[5] not in contactList:
            contactList.append(item[5])
    #print(contactList)

    fruitPrice=[]
    for fruit in fruitList:
        price = []
        for item in fruitInfo:
            if fruit==item[3]:
                #为了处理特殊价格如'0.78-1.5',采用如下处理方法,提取每个价格,并求平均值
                valStr=re.findall(r"[0-9,.]*",item[4])
                valStr=list(filter(None, valStr))
                avg=float(valStr[0])
                if len(valStr)>1:
                    sumVal = 0.0;
                    for i in valStr:
                        sumVal += float(i)
                    avg = round(sumVal/len(valStr),2)
                    #print("平均价格",valStr,avg)
                #去掉异常价格,当前价格是现有平均价格的10倍
                if len(price)>=1 and avg > (sum(price)/len(price))*10:
                    continue
                price.append(avg)
        fruitPrice.append([fruit,price])
    return fruitPrice

if __name__ == '__main__':
    #提取水果信息,提取3页
    fruitInfo = GetFruitInfo(3)
    # for i in fruitInfo:
    #     print(i)
    #从水果信息表内整理出价格信息
    priceInfo=FruitPriceInfo(fruitInfo)
    # for i in priceInfo:
    #     print(i)
    #输出各水果的平均价最低价最高价
    for i in priceInfo:
        print("{0},平均价格:{1},最低价格:{2},最高价格:{3}".format(i[0],round(sum(i[1])/len(i[1]),2),min(i[1]),max(i[1])))

    #绘制价格分布散点图
    plt.rcParams['font.sans-serif'] = ['SimHei']  # 显示中文标签
    #绘制脐橙的价格分布
    for i in range(len(priceInfo)):
        if priceInfo[i][0]=="脐橙":
            break
    #生成水平坐标数值,0~len(priceInfo[i][1]),步进为1,数据类型为整数
    xLine=np.arange(0,len(priceInfo[i][1]),1,dtype=np.int32)
    # 'bo-' 中b代表绿色,o代表原点,-代表直线,label指定标签
    plt.plot(xLine,priceInfo[i][1],'bo-',label="脐橙")
    # 绘制椪柑的价格分布
    for i in range(len(priceInfo)):
        if priceInfo[i][0] == "椪柑":
            break
    xLine = np.arange(0, len(priceInfo[i][1]), 1, dtype=np.int32)
    plt.plot(xLine,priceInfo[i][1],'ro-',label="椪柑")

    plt.title("脐橙价格分布", fontsize=24)
    plt.xlabel("序号",fontsize = 14)
    plt.ylabel("价格",fontsize = 14)
    #图中显示标签
    plt.legend()

    plt.show()

联系

有兴趣朋友交流邮箱:[email protected]

版权声明:本文为a394474295原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/a394474295/article/details/106041576