继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

教隔壁小姐姐搭建Python爬虫比价网站

慕虎7371278
关注TA
已关注
手记 1250
粉丝 203
获赞 873

01 基础知识

为了让小姐姐能听懂,我提前跟她说了要预习的知识。

webp

微信图片

当然,小姐姐也是有一定python基础的,有了上面的准备,相信我们一定能做一个深入的学习讨论。

02 实现思路

这个项目主要由三个部分组成

  • 爬虫:爬取京东、1号店和淘宝的商品信息实现价格比较

  • Flask:运用Flask构建Web应用,显示爬虫结果

  • pythonanywhere:通过pythonanywhere将Web应用部署到云

webp

实现思路

03 爬虫

第一步是用python爬虫脚本抓取网页上的商品信息,这里我们主要对京东、1号店和淘宝的商品信息进行爬取。不同的网页需要进行不同的分析,但方法都是大同小异的。我们先以1号店为例看看如何编写爬虫代码。

一、爬取1号店的商品数据

开始之前我们需要引入下面的python库:

import requestsfrom lxml import htmlimport urllib.parse

接下来,我们定义函数crawler:

def crawler(word, products_list=[]):

这里的word就是我们需要搜索商品名称,而products_list用来保存我们的爬取结果。

word = urllib.parse.quote(word)

当我们查询的商品名称含有中文时,是要对其进行编码处理的,urllib.parse.quote()函数可以帮助实现这一点。
当我们在1号店搜索商品名称时,其实是发起了一个url请求,这个url中包含了我们要查询的信息。因此我们需要将word参数加入到url中。

url = 'https://search.yhd.com/c0-0/k{0}'.format(word)

接下来的三步顺其自然,获取html源码,将html源码转换为xpath对象,然后在html树状结构中寻找包含商品信息的节点。

# 获取html源码html_doc = requests.get(url).text# xpath对象selector = html.fromstring(html_doc)# 商品列表ul_list = selector.xpath('//div[@id="itemSearchList"]/div')

得到了当前页面的商品列表之后,我们需要对其进行遍历获取其中每个商品的名称、价格、购买链接和店铺信息。

    for li in ul_list:        # 名称
        title = li.xpath('div//p[@class="proName clearfix"]/a/@title')        # 链接
        link = li.xpath('div//p[@class="proName clearfix"]/a/@href')        # 价格
        price = li.xpath('div//p[@class="proPrice"]/em/@yhdprice')        # 店铺
        store = li.xpath('div//p[@class="storeName limit_width"]/a/@title')

最后将我们爬取到的结果,存入products_list中为最后的价格比较做准备。

products_list.append({                'title': title[0],                'price': price[0],                'link': 'https:' + link[0],                'store': store[0],                'referer': '1号店'
            })

二、爬取京东的商品数据

京东商品信息的爬取与1号店十分相似,需要注意的是京东网页获取html信息后,需要进行utf-8编码才能正常显示页面。
直接上源码:

import requestsfrom lxml import htmldef crawler(word, products_list=[]):
    """ 爬取京东的商品数据 """
    url = 'https://search.jd.com/Search?keyword={0}&enc=utf-8'.format(word)    # 获取HTML文档
    respons = requests.get(url)
    respons.encoding = 'utf-8'
    html_doc = respons.text    # 获取xpath对象
    selector = html.fromstring(html_doc)    # 找到列表的集合
    ul_list = selector.xpath('//div[@id="J_goodsList"]/ul/li')    # 解析对应的标题,价格,链接,店铺
    for li in ul_list:        # 标题
        title = li.xpath('div/div[@class="p-name p-name-type-2"]/a/em/text() | '
                         'div/div[@class="p-name"]/a/@title')        # 购买链接
        link = li.xpath('div/div[@class="p-name p-name-type-2"]/a/@href | '
                        'div/div[@class="p-name"]/a/@href')        # 价格
        price = li.xpath('div/div[@class="p-price"]/strong/i/text() | '
                         'div/div[@class="p-price"]/strong/i/text()')        # 店铺
        store = li.xpath('div/div[@class="p-shop"]//a/text() | '
                         'div//a[@class="curr-shop"]/@title')

        products_list.append({                'title': title[0],                'price': price[0],                'link': 'https:' + link[0],                'store': store[0],                'referer': '京东'
            })if __name__ == '__main__':
    a = []
    crawler('爬虫', a)

三、爬取淘宝商品信息

淘宝商品信息的爬取就和前面两者有很大不同了,这里我们无法用xpath寻找包含商品信息的节点,查看网页源代码会发现根本就没有包含商品信息的html标签。这主要是因为淘宝是通过传递json数据来更新页面数据的。

因此这里的url不是一个网址,而是一个api接口:

url = 'https://s.taobao.com/api?ajax=true&m=customized&sourceId=tb.index&q={0}'.format(word)

当我们得到了淘宝传递的json数据后,后面的过程就很简单了,在json中寻找目标信息要比在html树状结构中寻找方便多了。

源码如下:

import requestsimport urllib.parsedef crawler(word, products_list=[]):
    """ 爬取淘宝网的商品数据 """
    word = urllib.parse.quote(word)

    url = 'https://s.taobao.com/api?ajax=true&m=customized&sourceId=tb.index&q={0}'.format(word)
    rest = requests.get(url).json()
    pr_list = rest["API.CustomizedApi"]["itemlist"]["auctions"]    for bk in pr_list:
        title = bk['raw_title']
        price = bk['view_price']
        link = bk['detail_url']
        store = bk['nick']
      
        products_list.append({            'title': title,            'price': price,            'link': 'https:' + link,            'store': store,            'referer': '淘宝'
        })if __name__ == '__main__':
    a = []
    crawler('python', a)

四、综合比价

综合比价需要我们导入前面三个爬虫脚本,并按价格由低到高的排序得到最终结果。

from crawler_jd import  crawler as jdfrom crawler_yhd import crawler as yhdfrom crawler_taobao import crawler as taobaodef main(word):
    """ 比价工具整合 """
    products_list = []    # 京东数据
    print('京东网数据爬取完成')
    jd(word, products_list)    # 1号店数据
    print('1号店数据爬取完成')
    yhd(word, products_list)    # 淘宝数据
    print('淘宝网数据爬取完成')
    taobao(word, products_list)

    print('-------------------------开始排序---------------------------------')    # 排序书的数据
    products_list = sorted(products_list, key=lambda item: float(item['price']), reverse=False)    for products in products_list:
        print(products)    return products_listif __name__ == '__main__':
    word = input('请输入商品名称:')
    main(word)

04 Flask

Flask提供了一组模块,可以帮助我们构建服务器端Web应用,由于我们的爬虫网站功能简单,所以Flask这个轻量级的框架就够了。

from flask import Flask, render_template, requestfrom crawler_product import main

app = Flask(__name__)@app.route('/')def entry_page() -> 'html':
    return render_template('entry.html',
                           the_title='Welcome to PriceCompare!')@app.route('/compare', methods=['POST'])def search_products() -> str:
    word = request.form['word']
    title = '比价结果'
    titles = ('商品', '价格', '链接', '店铺', '来源')
    results = main(word)    return render_template('results.html',
                           the_word=word,
                           the_title=title,
                           the_row_titles=titles,
                           the_data=results,)


app.run()

entry_page明确了Flask web应用的初始页面是entry.html,并向其中传入了我们想要显示的信息。
entry.html源码:

{% extends 'base.html' %}

{% block body %}<h2>{{ the_title }}</h2><form method='POST' action='/compare'><table><p>请输入想要比价的商品:</p><tr><td>商品:</td><td><input name='word' type='TEXT' width='60'></td></tr></table><p>准备好了,点击这里:</p><p><input value='Do it!' type='SUBMIT'></p></form>{% endblock %}

search_products接收了entry.html传入的word参数,并交由crawler_product进行爬虫,最后向results.html传递爬虫结果。
results.html源码:

{% extends 'base.html' %}

{% block body %}<h2>{{ the_title }}</h2><p>你提交的商品名称:</p><table><tr><td>关键字:</td><td>{{ the_word }}</td></tr></table><p>下面是 "{{ the_word }}" 的搜索比价结果:</p><table>
    <tr>
        {% for row_title in the_row_titles %}            <th>{{row_title}}</th>
        {% endfor %}    </tr>
    {% for products in the_data %}    <tr>
        <td>{{products['title']}}</td>
        <td>{{products['price']}}</td>
        <td><a href={{products['link']}}>{{products['link']}}</a></td>
        <td>{{products['store']}}</td>
        <td>{{products['referer']}}</td>
    </tr>
    {% endfor %}</table>{% endblock %}

到这里我们所有的代码都已经准备完毕,我们可以看看整个项目的源码结构:

webp

项目结构

crawler_jd.pycrawler_yhd.pycrawler_taobao.py分别为三个网页的爬虫脚本,通过crawler_product.py进行综合比较。

Flask_PriceCompaer.py是Flask Web应用核心代码,创建Flask对象并传递数据。

templates文件夹下的base.html是前端页面的基模板,entry.html继承了基模板负责网站进入页面的显示,results.htmlentry.html类似,负责网站结果页面的显示。
static文件夹下的hf.css就是普通的css文件,负责页面的美化。

我们可以运行Flas_PriceCompaer.py来看看网站的整体效果。

页面入口:

webp

entry

查询结果:

webp

results

源码下载

05 pythonanywhere

最后,只要10分钟就可以把我们的Web应用部署到云上,通过公网快捷地访问Python爬虫比价网站。

一、注册Pythonanywhere

将网站源代码打包压缩,访问pythonanywhere.com,并进行注册。

二、将文件上传到云

webp

文件上传

三、解压缩和安装代码

文件上传后,点击Open Bash console here,Pythonanywhere会弹出Linux控制台,我们执行两条命令:
unzip PriceCompaer.zip
mv PriceCompaer/* mysite/
将web应用的代码安装到mysite文件夹。

四、创建一个初始Web应用

webp

创建Web应用

点击Add a new web app后,一路next,并选择web framework为Flask以及相应python版本。

五、配置Web应用

接下来我们点击下图提示的位置:

webp

5.PNG

修改from flask_app import app as application,将flask_app修改为我们自己的Flask Web应用代码,如Flask_PriceCompaer。同时,我们也要查看Flask_PriceCompaer.py  文件,确保最后没有app.run()

六、运行

配置完成后,就可以点击那个绿色的Reload按钮开始运行了。

PS:要提醒的是,pythonanywhere免费版只能访问特定的网站,所以爬虫程序无法运行,想体检完整结果请自行升级收费版。

06 写在最后

这篇文章主要是记录自己的实现思路以及方法,其中的原理并没有进行详细的阐述。虽然主要是因为那样写的话太累了,但更重要的是,爬虫、Flask和pythonanywhere网上都有大量的教程,在大神们的教程里浪费时间才更有意义。



作者:Ackerzy
链接:https://www.jianshu.com/p/0e8f4d2da3d9


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP