01 基础知识
为了让小姐姐能听懂,我提前跟她说了要预习的知识。
微信图片
当然,小姐姐也是有一定python基础的,有了上面的准备,相信我们一定能做一个深入的学习讨论。
02 实现思路
这个项目主要由三个部分组成
爬虫:爬取京东、1号店和淘宝的商品信息实现价格比较
Flask:运用Flask构建Web应用,显示爬虫结果
pythonanywhere:通过pythonanywhere将Web应用部署到云
实现思路
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 %}
到这里我们所有的代码都已经准备完毕,我们可以看看整个项目的源码结构:
项目结构
crawler_jd.py
、crawler_yhd.py
、crawler_taobao.py
分别为三个网页的爬虫脚本,通过crawler_product.py
进行综合比较。
Flask_PriceCompaer.py
是Flask Web应用核心代码,创建Flask对象并传递数据。
templates
文件夹下的base.html
是前端页面的基模板,entry.html
继承了基模板负责网站进入页面的显示,results.html
与entry.html
类似,负责网站结果页面的显示。static
文件夹下的hf.css
就是普通的css文件,负责页面的美化。
我们可以运行Flas_PriceCompaer.py
来看看网站的整体效果。
页面入口:
entry
查询结果:
results
05 pythonanywhere
最后,只要10分钟就可以把我们的Web应用部署到云上,通过公网快捷地访问Python爬虫比价网站。
一、注册Pythonanywhere
将网站源代码打包压缩,访问pythonanywhere.com,并进行注册。
二、将文件上传到云
文件上传
三、解压缩和安装代码
文件上传后,点击Open Bash console here
,Pythonanywhere会弹出Linux控制台,我们执行两条命令:unzip PriceCompaer.zip
mv PriceCompaer/* mysite/
将web应用的代码安装到mysite
文件夹。
四、创建一个初始Web应用
创建Web应用
点击Add a new web app
后,一路next,并选择web framework为Flask以及相应python版本。
五、配置Web应用
接下来我们点击下图提示的位置:
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