crawler-10 淘宝商品比价定向爬虫

crawler-10 淘宝商品比价定向爬虫

1、目标网站:淘宝网

1
https://s.taobao.com/

19dz8S.png

2、查看robots协议

1
2
3
4
5
6
7
8
9
10
11
https://s.taobao.com/robots.txt

#结果
User-agent: *
Disallow: /

#含义
禁止任何爬虫爬取所有内容

#注意
类人行为可以不遵守robots协议,因此这里探讨技术实现可以爬取,但请不要不加限制地爬取该网站

3、注意

  这个例子仅探讨技术实现,请不要不加限制的爬取该网!

4、功能描述

1)目标:获取淘宝搜索页面的信息,提取其中的商品名称和价格

2)理解: 淘宝的搜索接口

3)难点:翻页的处理

4)技术路线:requests‐re

5、浏览网站

1)登录之后,在淘宝网搜索“书包”,在结果页面进行翻页,观察网址变化。

1
2
3
4
5
6
7
8
#起始页
https://s.taobao.com/search?initiative_id=staobaoz_20200119&q=书包

#第二页
https://s.taobao.com/search?initiative_id=staobaoz_20200119&q=书包&bcoffset=3&ntoffset=3&p4ppushleft=1%2C48&s=44

#第三页
https://s.taobao.com/search?initiative_id=staobaoz_20200119&q=书包&bcoffset=0&ntoffset=6&p4ppushleft=1%2C48&s=88

2)结果分析

1
2
3
4
5
6
7
8
#搜索接口
https://s.taobao.com/search?initiative_id=staobaoz_20200119&q=
舍弃无关紧要的参数,将接口简化为:https://s.taobao.com/search?q=

#翻页的URL对应属性
s=44
s=88
这里可以数一下,淘宝每页书包商品数量恰好是44个,这个s变量表示的是某一页的起始商品的编号

5、程序的结构设计

1)提交商品搜索请求,循环获取页面:getHtmlText(url);

2)对于每个页面,提取商品名称和价格信息:parsePage(ilt,html);

3)将信息输出到屏幕上:printGoodsList(ilt);

6、程序实例编写

1)程序框架

  按照上一步骤中设计好的程序结构,先将程序整体的框架搭建起来,更利于我们有一个清晰的思路来编写代码。此程序整体思路就是,循环获取多个页面的信息,保存到 ilt 列表中,最后将该列表打印。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import requests
import re
def getHtmlText(url):
try:
r=requests.get(url=url,timeout=30)
r.raise_for_status()
r.encoding=r.apparent_encoding
return r.text
except:
print("")

def parsePage(ilt,html):
print("")


def printGoodsList(ilt):
print("")


def main():
goods="书包"
depth=3 #页面深度
start_url='https://s.taobao.com/search?q=' + goods
infoList=[]
for i in range(depth):
try:
url=start_url+'&s='+str(44*i) #针对每个页面构建其url
html=getHtmlText(url)
parsePage(infoList,html)
except:
continue #某一页面爬取异常,不会影响其他页面
printGoodsList(infoList)


if __name__ == '__main__':
main()

备注

1
2
3
4
#这里的变量命名
ilt:info_list
plt:price_list
tlt:title_list

2)具体实现

a)右键查看网页源代码,如下图,有一款书包价格为149.00,那么可以直接搜索149.00;

1C8sfJ.png

1C8wwT.png

b)可以看到,价格信息保存在一个view_price键值对里面;

1C8X0f.png

c)接下来检索商品名称,同样可以看到商品标题名称保存在raw_title键值对里面。

1CGMcR.png

d)用正则表达式提所需信息

1
2
3
4
5
6
7
8
9
#所需信息在网页源码里面的体现如下
"view_price":"149.00"
"raw_title":"小米双肩包简约休闲多功能书包男女笔记本电脑包时尚潮流旅行背包"

在正则表达式的原生字符串表示下,上述字符串的双引号和冒号以及点号都需要转义,不然例如点号在正则表达式里表示任意单个字符,就会证乱套了。

因此,上述信息在正则表达式中的体现如下:
r'\"view_price\"\:\"149\.00\"'
r'\"raw_title\"\:\"小米双肩包简约休闲多功能书包男女笔记本电脑包时尚潮流旅行背包\"'

价格数值匹配举例:

1
2
3
4
5
6
7
8
9
10
import re
ls=re.findall(r'price\:[\d\.]*','time:2019 time:2018 time:2017 price:11.2 price:22.3 price:55.5.2.3')
print(ls)

#运行结果
['price:11.2', 'price:22.3', 'price:55.5.2.3']

#分析
[\d\.]*的含义是:[单个数字或者小数点]前一个字符0次或无限次扩展
意思就是对数字或者小数点的无限扩展,因此可以匹配带小数点的这些价格数值

标题匹配举例

1
2
3
4
5
6
7
8
9
10
import re
ls = re.findall(r'\"raw_title\:.*?\"','"raw_title:aaa" "raw_title:bbb"')
print(ls)

#运行结果
['"raw_title:aaa"', '"raw_title:bbb"']

#分析
.*?的含义是:任意字符无限次扩展,且使用最小匹配(而不是贪婪匹配)
这样即可匹配类似"小米双肩包简约休闲多功能书包男女笔记本电脑包时尚潮流旅行背包"这样的标题

综上,提取商品名称和价格所需的正则表达式即如下

1
2
\"view_price\"\:\"[\d\.]*\"
\"raw_title\"\:\".*?\"

e)利用eval函数去除双引号, eval() 函数用来执行一个字符串表达式,并返回表达式的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import re
ls = ['"view_price":"149.00"','"view_price":"145.00"']
print(ls)

for i in range(len(ls)):
print(eval(ls[i].split(":")[1]))
print(ls[i].split(":")[1])

#执行结果
['"view_price":"149.00"', '"view_price":"145.00"']
149.00
"149.00"
145.00
"145.00"


#扩展
>>>x = 7
>>> eval( '3 * x' )
21
>>> eval('pow(2,2)')
4

f)parsePage(ilt,html)函数的实现

1
2
3
4
5
6
7
8
9
10
def parsePage(ilt,html):
try:
plt=re.findall(r'\"view_price\"\:\"[\d\.]*\"',html)
tlt=re.findall(r'\"raw_title\"\:\".*?\"',html)
for i in range(len(plt)):
price=eval(plt[i].split(":")[1])
title=eval(tlt[i].split(":")[1])
ilt.append([price,title])
except:
print("")

g)printGoodsList(ilt)函数的实现

1
2
3
4
5
6
7
def printGoodsList(ilt):
tplt="{:4}\t{:8}\t{:16}" #定义模板tplt,三列长度分别为4/8/16
print(tplt.format("序号","价格","商品名称"))
count=0
for g in ilt:
count=count+1
print(tplt.format(count,g[0],g[1]))

3)整体源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import requests
import re

def getHTMLText(url):
try:
r = requests.get(url, timeout=30)
r.raise_for_status()
r.encoding = r.apparent_encoding
return r.text
except:
return ""

def parsePage(ilt, html):
try:
plt = re.findall(r'\"view_price\"\:\"[\d\.]*\"',html)
tlt = re.findall(r'\"raw_title\"\:\".*?\"',html)
for i in range(len(plt)):
price = eval(plt[i].split(':')[1])
title = eval(tlt[i].split(':')[1])
ilt.append([price , title])
except:
print("")

def printGoodsList(ilt):
tplt = "{:4}\t{:8}\t{:16}"
print(tplt.format("序号", "价格", "商品名称"))
count = 0
for g in ilt:
count = count + 1
print(tplt.format(count, g[0], g[1]))

def main():
goods = '书包'
depth = 3
start_url = 'http://s.taobao.com/search?q=' + goods
infoList = []
for i in range(depth):
try:
url = start_url + '&s=' + str(44*i)
html = getHTMLText(url)
parsePage(infoList, html)
except:
continue
printGoodsList(infoList)

if __name__ == '__main__':
main()

7、问题与解决办法

  上面的源码并不能爬取淘宝页面的商品,原因是该源码教程均是慕课网上几年前编写的,现在淘宝网做了登录验证功能,即使在浏览器上,打开淘宝网上搜索“书包”也必须要登录才能看到搜索结果。因此对于上述代码必须加以改进才能实现功能。

  解决办法:暂时没有,按照网上的教程,加了cookie也没成功。

欢迎打赏,谢谢
------ 本文结束------
0%