
一、淘宝登录复习
前面我们已经介绍过了如何使用requests库登录淘宝,收到了很多同学的反馈和提问,猪哥感到很欣慰,同时对那些没有及时回复的同学说声抱歉!
顺便再提一下这个登录功能,代码是完全没有问题。如果你登录出现申请st码失败的错误时候,可以更换_verify_password方法中的所有请求参数。

二、淘宝商品信息爬取
这篇文章主要是讲解如何爬取数据,数据的分析放在下一篇。之所以分开是因为爬取淘宝遇到的问题太多,而猪哥又打算详细再详细的为大家讲解如何爬取,所以考虑篇幅及同学吸收率方面就分两篇讲解吧!宗旨还会不变:让小白也能看得懂!
本次爬取是调用淘宝pc端搜索接口,对返回的数据进行提取、然后保存为excel文件!
看似一个简单的功能却包含了很多问题,我们来一点一点往下看吧!
三、爬取单页数据
开始写一个爬虫项目我们都需要量化后再分步,而一般第一步便是先爬取一页试试!
1.查找加载数据URL
我们在网页中打开淘宝网,然后登录,打开chrome的调试窗口,点击network,然后勾选上Preserve log,在搜索框中输入你想要搜索的商品名称

这是第一页的请求,我们查看了数据发现:返回的商品信息数据插入到了网页里面,而不是直接返回的纯json数据!

2. 是否有返回纯json数据接口?
然后就好奇有没有返回纯json的数据接口呢?于是我就点了下一页(也就是第二页)

请求第二页后猪哥发现返回的数据竟然是纯json,然后比较两次请求url,找到只返回json数据的参数!

通过比较我们发现搜索请求url中如果带ajax=true参数的话就直接返回json数据,那我们是不是可以直接模拟直接请求json数据!
所以就直接使用第二页的请求参数去请求数据(也就是直接请求json数据),但是请求第一页就出现错误:

直接返回一个链接而 不是json数据,这个链接是什么鬼?点一下。。。

铛铛铛,滑块出现,有同学会问:**用requests能搞定淘宝滑块吗?**猪哥咨询过几个爬虫大佬,滑块的原理是收集响应时间,拖拽速度,时间,位置,轨迹,重试次数等然后判断是否是人工滑动。而且还经常变算法,所以猪哥选择放弃这条路!
3.使用请求网页接口
所以我们选择类似第一页(请求url中不带ajax=true参数,返回整个网页形式)的请求接口,然后再把数据提取出来!

这样我们就可以爬取到淘宝的网页信息了
四、提取商品属性
爬到网页之后,我们要做的就是提取数据,这里先从网页提取json数据,然后解析json获取想要的属性。
1.提取网页中商品json数据
既然我们选择了请求整个网页,我们就需要了解数据内嵌在网页的哪个位置,该怎么提取出来。
经过搜索比较发现,返回网页中的js参数:g_page_config就是我们要的商品信息,而且也是json数据格式!

然后我们写一个正则就可以将数据提取出来了!
goods_match = re.search(r'g_page_config = (.*?)}};', response.text)
2.获取商品价格等信息
要想提取json数据,就要了解返回json数据的结构,我们可以将数据复制到一些json插件或在线解析

了解json数据结构之后,我们就可以写一个方法去提取我们想要的属性了

五、保存为excel
操作excel有很多库,网上有人专门针对excel操作库做了对比与测评感兴趣可以看看:https://dwz.cn/M6D8AQnq
猪哥选择使用pandas库来操作excel,原因是pandas比较操作方便且是比较常用数据分析库!
1.安装库
pandas库操作excel其实是依赖其他的一些库,所以我们需要安装多个库
pip install xlrd
pip install openpyxl
pip install numpy
pip install pandas
2.保存excel

这里有点坑的是pandas操作excel没有追加模式,只能先读取数据后使用append追加再写入excel!
查看效果

六、批量
一次爬取的整个流程(爬取、数据提取、保存)完成之后,我们就可以批量循环调用了。

这里设置的超时秒数是实践出来的,从3s、5s到10s以上,太频繁容易出现验证码!

分多次爬取了两千多条数据

七、爬取淘宝遇到的问题
爬取淘宝遇到了非常多的问题,这里为大家一一列举:
1.登录问题

问题:申请st码失败怎么办?
回答:更换_verify_password方法中的所有请求参数。
参数没问题的话登录基本都会成功!
2.代理池
为了防止自己的ip被封,猪哥使用了代理池。爬取淘宝需要高质量的ip才能爬取,猪哥试了很多网上免费的ip,基本都不能爬取。

但是有一个网站的ip很好 站大爷:http://ip.zdaye.com/dayProxy.html ,这个网站每小时都会更新一批ip,猪哥试过还是有很多ip是可以爬取淘宝的。
3.重试机制
为了防止正常请求失败,猪哥在爬取的方法上加上了重试机制!

需要安装retry库
pip install retry
4.出现滑块
上面那些都没问题,但是还是会出现滑块,测试过很多次,有些爬取20次-40次左右最容易出现滑块。

出现滑块只能等个半小时后继续爬,因为目前还不能使用requests库解决滑块,后面学习selenium等其他框架看看是否能解决!
5.目前这只爬虫
目前这只爬虫并不完善,只能算是半成品,有很多可以改进的地方,比如自动维护ip池功能,多线程分段爬取功能,解决滑块问题等等,后面我们一起来慢慢完善这只爬虫,使他可以成为一只完善懂事的爬虫!
完整代码
import os
import re
import json
import time
import random
import requests
import pandas as pd
from retrying import retry
from taobao_login import TaoBaoLogin
'''
遇到不懂的问题?Python学习交流群:821460695满足你的需求,资料都已经上传群文件,可以自行*载下**!
'''
# 关闭警告
requests.packages.urllib3.disable_warnings()
# 登录与爬取需使用同一个Session对象
req_session = requests.Session()
# 淘宝商品excel文件保存路径
GOODS_EXCEL_PATH = 'taobao_goods.xlsx'
class GoodsSpider:
def __init__(self, q):
self.q = q
# 超时
self.timeout = 15
self.goods_list = []
# 淘宝登录
tbl = TaoBaoLogin(req_session)
tbl.login()
@retry(stop_max_attempt_number=3)
def spider_goods(self, page):
"""
:param page: 淘宝分页参数
:return:
"""
s = page * 44
# 搜索链接,q参数表示搜索关键字,s=page*44 数据开始索引
search_url = f'https://s.taobao.com/search?initiative_id=tbindexz_20170306&ie=utf8&spm=a21bo.2017.201856-taobao-item.2&sourceId=tb.index&search_type=item&ssid=s5-e&commend=all&imgfile=&q={self.q}&suggest=history_1&_input_charset=utf-8&wq=biyunt&suggest_query=biyunt&source=suggest&bcoffset=4&p4ppushleft=%2C48&s={s}&data-key=s&data-value={s + 44}'
# 代理ip,网上搜一个,猪哥使用的是 站大爷:http://ip.zdaye.com/dayProxy.html
# 尽量使用最新的,可能某些ip不能使用,多试几个。后期可以考虑做一个ip池
# 爬取淘宝ip要求很高,西刺代理免费ip基本都不能用,如果不能爬取就更换代理ip
proxies = {'http': '118.24.172.149:1080',
'https': '60.205.202.3:3128'
}
# 请求头
headers = {
'referer': 'https://www.taobao.com/',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
}
response = req_session.get(search_url, headers=headers, proxies=proxies,
verify=False, timeout=self.timeout)
# print(response.text)
goods_match = re.search(r'g_page_config = (.*?)}};', response.text)
# 没有匹配到数据
if not goods_match:
print('提取页面中的数据失败!')
print(response.text)
raise RuntimeError
goods_str = goods_match.group(1) + '}}'
goods_list = self._get_goods_info(goods_str)
self._save_excel(goods_list)
# print(goods_str)
def _get_goods_info(self, goods_str):
"""
解析json数据,并提取标题、价格、商家地址、销量、评价地址
:param goods_str: string格式数据
:return:
"""
goods_json = json.loads(goods_str)
goods_items = goods_json['mods']['itemlist']['data']['auctions']
goods_list = []
for goods_item in goods_items:
goods = {'title': goods_item['raw_title'],
'price': goods_item['view_price'],
'location': goods_item['item_loc'],
'sales': goods_item['view_sales'],
'comment_url': goods_item['comment_url']}
goods_list.append(goods)
return goods_list
def _save_excel(self, goods_list):
"""
将json数据生成excel文件
:param goods_list: 商品数据
:param startrow: 数据写入开始行
:return:
"""
# pandas没有对excel没有追加模式,只能先读后写
if os.path.exists(GOODS_EXCEL_PATH):
df = pd.read_excel(GOODS_EXCEL_PATH)
df = df.append(goods_list)
else:
df = pd.DataFrame(goods_list)
writer = pd.ExcelWriter(GOODS_EXCEL_PATH)
# columns参数用于指定生成的excel中列的顺序
df.to_excel(excel_writer=writer, columns=['title', 'price', 'location', 'sales', 'comment_url'], index=False,
encoding='utf-8', sheet_name='Sheet')
writer.save()
writer.close()
def patch_spider_goods(self):
"""
批量爬取淘宝商品
如果爬取20多页不能爬,可以分段爬取
:return:
"""
# 写入数据前先清空之前的数据
if os.path.exists(GOODS_EXCEL_PATH):
os.remove(GOODS_EXCEL_PATH)
# 批量爬取,自己尝试时建议先爬取3页试试
for i in range(0, 100):
print('第%d页' % (i + 1))
self.spider_goods(i)
# 设置一个时间间隔
time.sleep(random.randint(10, 15))
if __name__ == '__main__':
gs = GoodsSpider('避孕套')
gs.patch_spider_goods()