基于网络爬虫的商品询价系统的设计与实现(Python)

这篇具有很好参考价值的文章主要介绍了基于网络爬虫的商品询价系统的设计与实现(Python)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录
一、前言 1
1.1 背景 1
1.2 用到的技术简述 1
1.2.1 网络爬虫技术 2
1.2.2 UI设计 3
1.2.3 数据库设计 3
二、设计过程 3
2.1 面向对象设计 3
2.1.1 由需求导出用例图 4
2.1.2 类的确定 4
2.1.3 实体类的设计 6
2.1.4 功能类的设计 6
cursor.execute( 6
2.2 UI设计 11
一、前言
1.1 背景
近几年来网络购物越来越流行,基本上每个人都有过网购经历,本着“货比三家”的原则,我们往往倾向于对商品进行大量的比较。然而不同的网购平台其商品也不尽相通,而跨网站的比较又着实比较麻烦,因此就有了做一个快捷的网购平台比价系统的想法,实现在一个界面内实现多网购平台商品的比价操作。

其实很早就萌生了做这个程序的念头,但是一直都觉得实现起来比较麻烦所以就鸽了,但是由于在做学校的Python课设时没有好的想法,就还是把这个给提了出来,真正实现之后发现也并不是很难。

1.2 用到的技术简述
既然是比价系统,就肯定要实现数据的获取,那么就难免需要网络爬虫技术、数据库技术以及简单的UI设计。

1.2.1 网络爬虫技术
我们用到的是requests+selenium的方法进行爬虫,其实简单的爬虫用不到selenium,requests就足够了,但是有些网站不是静态加载的,我们用requests就获取不到数据,因此这里也用一下selenium,以便于进行扩展。

requests:可以直接利用get方法获取目标页面的HTML文本,使用起来十分简单。
selenium:可以实现模拟操作,其操作可以做到与手动一样,从而获取页面的文本(手动操作即在页面上右键->查看源代码从而获取HTML文本),虽然可能会有点慢,但是可以很好的绕过网站的反爬虫程序。

既然已经获取到了HTML文本,那么就肯定需要进行解析,从而获取到我们想要的数据。常用的解析方法是BeautifulSoup和正则表达式re。

BeautifulSoup:利用HTML中的标签进行查找,在查找目标数据时需要观察目标数据在哪个Tag下,可以利用父Tag到子Tag的方式逐级查找,或者利用目标数据所在Tag的位置进行查找(这个方法风险比较大,网页源码稍有改动就有可能完蛋)。例如以下HTML(只是做个示例,没有详细学过HTML,可能会写错还请勿喷):

a b c 比如我们想要获取tag2下的title(即b),我们可以先查找tag1,然后查找title,然后获取title中的内容;也可以直接查所有的title,在返回的列表中选择第二个,之后获取其下的内容。

正则表达式re:具体语法就不讲了,比较麻烦,不懂的可以自己查一下,这里给一个连接:正则表达式–菜鸟教程,学起来还是比较快的,值得一提的是,在HTML中利用正则表达式时往往需要进行最短匹配(默认的匹配是贪婪匹配),这就需要我们利用好“?”这个符号。以上面的例子为例,我们可以利用正则表达式<//tag1>.* ?

.<em>?<//title>来获取目标字符串,然后利用正则表达式<title>.?<//title>从该字符串中扣出来仅包含目标数据的字符串,从而可以利用下标来获取指定数据,比如此处我们可以选择第8—(-8)个字符来获取目标数据“b”(-8代表倒数第8),为了防止出现错误,在每次的匹配任意多个字符的时候最好都加上"?"。

1.2.2 UI设计
我们用到的是Python中的tkinter第三方库,可以很容易的实现简单的UI设计。涉及到的操作就是控件的布局、鼠标点击的响应事件、控件中数据的获取,都是一些比较简单的操作。这里简单放一下我设计的结果(设计的比较简陋,因为俺也是现学的这东西,不是很懂那些高级控件),具体操作我们后面说。

import tkinter as tk
from tkinter import ttk
import tkinter.messagebox
from GoodsList import GoodsList
from Goods import Goods
from DBConnection import DBConnection

class GUI:

    #用于存放商品信息
    goodsinfo = []
    #主窗口
    window = tk.Tk()
    #框架划分
    frm_t = tk.Frame(window, width=1000, height=300).pack()
    frm_b = tk.Frame(window, width=1000, height=600).pack()
    frm_d = tk.Frame(window, width=1000, height=100).pack()
    #平台选择
    tm_var = tk.IntVar()
    jd_var = tk.IntVar()
    pdd_var = tk.IntVar()
    c1 = tk.Checkbutton(frm_t, text='天猫', variable=tm_var, onvalue=1, offvalue=0)
    c2 = tk.Checkbutton(frm_t, text='京东', variable=jd_var, onvalue=1, offvalue=0)
    c3 = tk.Checkbutton(frm_t, text='拼多多', variable=pdd_var, onvalue=1, offvalue=0)
    #获取爬取商品数量
    dp_var = tk.IntVar()
    dp_en = tk.Entry(frm_t, textvariable=dp_var, width=3)
    #获取搜索关键词
    goods_var = tk.StringVar()
    goods_en = tk.Entry(frm_t, textvariable=goods_var, width=10)
    #排序方式
    sort_var = tk.IntVar()
    ch1 = tk.Radiobutton(frm_b, text='默认排序', variable=sort_var, value=1)
    ch2 = tk.Radiobutton(frm_b, text='价格升序', variable=sort_var, value=2)
    ch3 = tk.Radiobutton(frm_b, text='价格倒序', variable=sort_var, value=3)
    # 获取序号
    num_var = tk.StringVar()
    num_en = tk.Entry(frm_t, textvariable=num_var, width=50)
    #表格
    tree = ttk.Treeview(frm_d, columns=['1', '2', '3', '4', '5', '6', '7', '8'], show='headings', height=25)
    #表格滚动条
    VScroll1 = ttk.Scrollbar(tree, orient='vertical', command=tree.yview)
    #这个按钮后面在函数中需要变动,所以设为全局变量
    comfirm3 = tk.Button(frm_t, text='加入关注',  width=20)

    #获取信息
    def getInfo(self):
        self.comfirm3.config(text = '加入关注',command=self.addtoDB)
        self.goodsinfo.clear()
        tm = self.tm_var.get()
        jd = self.jd_var.get()
        pdd = self.pdd_var.get()
        number = self.dp_var.get()
        keyword = self.goods_var.get()
        if not tm and not jd and not pdd:
            tk.messagebox.showinfo(title='提示', message='您未选取任何平台')
            return
        check_numls=[]
        for i in range(60):
            check_numls.append(i+1)
        if number not in check_numls:
            tk.messagebox.showinfo(title='提示', message='请输入正确的爬取数量(1--60)')
            return
        if keyword == '':
            tk.messagebox.showinfo(title='提示', message='请输入关键词')
            return
        goodslist = GoodsList(keyword,number,tmall=tm,jd=jd,pdd=pdd)
        goodslist.getGoods()
        if self.sort_var.get() == 1:
            self.goodsinfo.extend(goodslist.getGoodsList())
        elif self.sort_var.get() == 2:
            self.goodsinfo.extend(goodslist.sort())
        else:
            self.goodsinfo.extend(goodslist.sort(reverse = True))
        self.showdata()
        tk.messagebox.showinfo(title='提示', message='爬取完成\n*拼多多商品销量为总销量,天猫销量为月销量')

    #显示信息
    def showdata(self):
        for item in self.tree.get_children():
            self.tree.delete(item)
        if not self.goodsinfo:
            tk.messagebox.showinfo(title = '提示',message = '当前无商品信息')
            return
        else:
            num = 1
            for goods in self.goodsinfo:
                goodslist = [num,goods.getID(),goods.getPlatform(),goods.getTitle(),goods.getShop(),goods.getPrice(),goods.getSales(),goods.getHref()]
                self.tree.insert('','end',values = goodslist)
                num = num+1

    #比价
    def compare(self):
        num_ls = self.num_var.get().split(' ')
        num_ls = list(set(num_ls))
        compare_ls = []
        for num in num_ls:
            if num == '':
                continue
            try:
                if not isinstance(eval(num), int):
                    tk.messagebox.showinfo(title='提示', message='请输入正确的序号')
                    return
                elif eval(num) > len(self.goodsinfo) or eval(num) < 1:
                    tk.messagebox.showinfo(title='提示', message='请输入正确的序号')
                    return
                else:
                    compare_ls.append(self.goodsinfo[eval(num)-1])
            except:
                tk.messagebox.showinfo(title='提示', message='请输入正确的序号')
                return
        goodslist = GoodsList('', 0)
        result = goodslist.compare(compare_ls)
        tk.messagebox.showinfo(title='比价结果', message=result)

    #加入关注列表
    def addtoDB(self):
        num_ls = self.num_var.get().split(' ')
        num_ls = list(set(num_ls))
        add_ls = []
        for num in num_ls:
            if num == '':
                continue
            try:
                if not isinstance(eval(num), int):
                    tk.messagebox.showinfo(title='提示', message='请输入正确的序号')
                    return
                elif eval(num) > len(self.goodsinfo) or eval(num) < 1:
                    tk.messagebox.showinfo(title='提示', message='请输入正确的序号')
                    return
                else:
                    add_ls.append(self.goodsinfo[eval(num) - 1])
            except:
                tk.messagebox.showinfo(title='提示', message='请输入正确的序号')
                return
        dbc = DBConnection()
        result = ''
        for item in add_ls:
            if dbc.save(item):
                result = result + '\"' + item.getTitle() + '\" 已成功加入关注列表\n'
            else:
                result = result + '\"' + item.getTitle() + '\" 已在关注列表中\n'
        tk.messagebox.showinfo(title='提示', message=result)

    #显示关注列表
    def showDB(self):
        self.comfirm3.config(text='移除关注', command=self.delete)
        self.goodsinfo = []
        dbc = DBConnection()
        g_ls = dbc.getInfo()
        for item in g_ls:
            goods = Goods(item[0],item[1],item[2],item[3],item[4],item[5],item[6])
            self.goodsinfo.append(goods)
        for item in self.tree.get_children():
            self.tree.delete(item)
        if not self.goodsinfo:
            tk.messagebox.showinfo(title = '提示',message = '当前关注列表无商品')
            return
        else:
            num = 1
            for goods in self.goodsinfo:
                li = [num,goods.getID(),goods.getPlatform(),goods.getTitle(),goods.getShop(),goods.getPrice(),goods.getSales(),goods.getHref()]
                self.tree.insert('','end',values =li)
                num = num+1

    #更新关注列表内容
    def updateDB(self):
        change_ls = []
        dbc = DBConnection()
        self.goodsinfo = []
        g_ls = dbc.getInfo()
        for item in g_ls:
            goods = Goods(item[0], item[1], item[2], item[3], item[4], item[5], item[6])
            self.goodsinfo.append(goods)
        for item in self.goodsinfo:
            change = item.update()
            if change != 0:
                change_ls.append([item.getTitle(),change])
        if change_ls:
            s = ''
            for item in change_ls:
                if item[1]>0:
                    s = s + '\"' + item[0] + '\" 价格增加了 ' + str(item[1]) + ' 元\n'
                else:
                    s = s + '\"' + item[0] + '\" 价格降低了 ' + str(abs(item[1])) + ' 元\n'
        else:
            s = '关注列表中所有商品价格均无变动'
        tk.messagebox.showinfo(title='提示', message=s)

    #从关注列表删除
    def delete(self):
        num_ls = self.num_var.get().split(' ')
        num_ls = list(set(num_ls))
        delete_ls = []
        for num in num_ls:
            if num == '':
                continue
            try:
                if not isinstance(eval(num), int):
                    tk.messagebox.showinfo(title='提示', message='请输入正确的序号')
                    return
                elif eval(num) > len(self.goodsinfo) or eval(num) < 1:
                    tk.messagebox.showinfo(title='提示', message='请输入正确的序号')
                    return
                else:
                    delete_ls.append(self.goodsinfo[eval(num) - 1])
            except:
                tk.messagebox.showinfo(title='提示', message='请输入正确的序号')
                return
        dbc = DBConnection()
        for item in delete_ls:
            dbc.delete(item)
        tk.messagebox.showinfo(title='提示', message='删除成功')

    #主窗口
    def mainwindow(self):
        self.window.title('网购平台比价系统')
        self.window.geometry('1150x700')

        # 网站选择
        tk.Label(self.frm_t, text='平台选择:').place(x=30, y=30)
        self.c1.place(x=100, y=28)
        self.tm_var.set(True)
        self.c2.place(x=170, y=28)
        self.jd_var.set(True)
        self.c3.place(x=240, y=28)
        self.pdd_var.set(True)

        # 商品数选择
        tk.Label(self.frm_t, text='每个平台爬取数量:').place(x=330, y=30)
        self.dp_en.place(x=445, y=30)
        self.dp_var.set(1)

        # 商品选择
        tk.Label(self.frm_t, text='关键词:').place(x=500, y=30)
        self.goods_en.place(x=555, y=30)

        # 排序
        tk.Label(self.frm_b, text='排序方式:').place(x=655, y=30)
        self.sort_var.set(1)
        self.ch1.place(x=720, y=30)
        self.ch2.place(x=800, y=30)
        self.ch3.place(x=880, y=30)

        # 商品选择
        tk.Label(self.frm_b, text='请输入序号:').place(x=30, y=90)
        self.num_en.place(x=105, y=90)
        self.num_var.set('(提示:若输入多个序号请用空格隔开)')

        # 确认
        comfirm1 = tk.Button(self.frm_t, text='开始爬取', command=self.getInfo, width=20)
        comfirm1.place(x=980, y=30)

        # 开始比价
        comfirm2 = tk.Button(self.frm_t, text='开始比价',command=self.compare, width=20)
        comfirm2.place(x=500, y=90)

        # 加入关注列表
        self.comfirm3.config(command=self.addtoDB)
        self.comfirm3.place(x=660, y=90)

        # 显示关注列表
        comfirm4 = tk.Button(self.frm_t, text='关注列表',command=self.showDB,width=20)
        comfirm4.place(x=820, y=90)

        # 更新关注列表
        comfirm4 = tk.Button(self.frm_t, text='更新关注商品价格',command=self.updateDB, width=20)
        comfirm4.place(x=980, y=90)

        # 划线
        canvas1 = tk.Canvas(self.frm_b, bg='white', width=1095, height=3)
        canvas1.place(x=30, y=130)
        canvas2 = tk.Canvas(self.frm_b, bg='white', width=1095, height=3)
        canvas2.place(x=30,y=70)

        # 打印表格头部
        self.tree.column('1', width=50, anchor='w')
        self.tree.heading('1', text='序号')
        self.tree.column('2', width=100, anchor='w')
        self.tree.heading('2', text='ID')
        self.tree.column('3', width=80, anchor='w')
        self.tree.heading('3', text='平台')
        self.tree.column('4', width=300, anchor='w')
        self.tree.heading('4', text='标题')
        self.tree.column('5', width=150, anchor='w')
        self.tree.heading('5', text='商铺')
        self.tree.column('6', width=80, anchor='w')
        self.tree.heading('6', text='价格')
        self.tree.column('7', width=80, anchor='w')
        self.tree.heading('7', text='销量')
        self.tree.column('8', width=255, anchor='w')
        self.tree.heading('8', text='链接')
        self.VScroll1.place(relx=0.979, rely=0, relwidth=0.020, relheight=1)
        self.tree.configure(yscrollcommand=self.VScroll1.set)
        self.tree.place(x=30, y=150)
        self.window.mainloop()

if __name__ =='__main__':
    ui = GUI()
    ui.mainwindow()

基于网络爬虫的商品询价系统的设计与实现(Python)
基于网络爬虫的商品询价系统的设计与实现(Python)
基于网络爬虫的商品询价系统的设计与实现(Python)
基于网络爬虫的商品询价系统的设计与实现(Python)
基于网络爬虫的商品询价系统的设计与实现(Python)
基于网络爬虫的商品询价系统的设计与实现(Python)
基于网络爬虫的商品询价系统的设计与实现(Python)
基于网络爬虫的商品询价系统的设计与实现(Python)
基于网络爬虫的商品询价系统的设计与实现(Python)
基于网络爬虫的商品询价系统的设计与实现(Python)
基于网络爬虫的商品询价系统的设计与实现(Python)
基于网络爬虫的商品询价系统的设计与实现(Python)
基于网络爬虫的商品询价系统的设计与实现(Python)文章来源地址https://www.toymoban.com/news/detail-446465.html

到了这里,关于基于网络爬虫的商品询价系统的设计与实现(Python)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包