[Python爬虫实战八之利用Selenium抓取淘宝匿名旺旺]
## 更新
其实本文的初衷是为了获取淘宝的非匿名旺旺,在淘宝详情页的最下方有相关评论,含有非匿名旺旺号,快一年了淘宝都没有修复这个。
可就在今天,淘宝把所有的账号设置成了匿名显示,SO,获取非匿名旺旺号已经不可能了。那本节就带大家抓取匿名旺旺号熟悉一下Selenium吧。
2016/7/1
## 前言
嗯,淘宝,它一直是个难搞的家伙。
~而且买家在买宝贝的时候大多数都是匿名评论的,大家都知道非匿名评论是非常有用的,比如对于大数据分析,分析某个宝贝的购买用户星级状况等等。~
现在已经不能获取非匿名了,此句已没有意义了。
对于抓淘宝,相信尝试过的童鞋都能体会到抓取它到艰辛,最简单的方法莫过于模拟浏览器了,本节我们就讲解一下利用 Selenium 抓取淘宝评论的方法。
项目提供了如下功能:
* 输入淘宝关键字采集淘宝链接并写入到文件
* 从文件读取链接,执行评论采集
* 将评论和旺旺号保存到Excel中
* 记录当前采集链接索引,保存进度
## 准备工作
在开始本节之前
你需要了解一些基础知识,我们需要用到 Selenium 这个东西,详情请看
[Selenium用法](http://cuiqingcai.com/2599.html)
我们首先讲解一下你需要做怎样的配置。
首先你需要安装 Python,版本是2.7
然后需要安装的 Python 类库。
1pip install pyquery selenium twisted requests xlrd xlwt xlutils
安装浏览器 Chrome,安装浏览器 Chrome,安装浏览器Chrome。
然后下载ChromeDriver,ChromeDriver是驱动浏览器的工具,需要把它配置到环境变量里。
有的童鞋说,为什么不用 PhantomJS,因为为了防止淘宝禁掉我们,需要登录淘宝账号,登录过程可能会出现奇奇怪怪得验证码,滚动条,手机验证,如果用 PhantomJS 的话不方便操作,所以在这里我们就使用 Chrome 了。
[ChromeDriver](http://chromedriver.storage.googleapis.com/index.html?path=2.7/)
上面是 ChromeDriver 的下载地址,谷歌都上得了,这个不在话下吧,这是最官方的版本,其他链接请自行搜索。
找到对应平台的 ChromeDriver,解压后将可执行文件配置到环境变量里,配置到环境变量里,配置到环境变量里!重要的话说三遍。
## 流程简述
首先我们拿一个例子来演示一下全过程。
随意打开天猫一个链接
[示例链接](https://world.tmall.com/item/45262540681.htm?spm=a220m.1000858.1000725.110.r7oyq2&id=45262540681&skuId=85225485607&areaId=320700&cat_id=50025145&rn=6f644caecfa85abefea71e2dc48ac6ae&user_id=2148264599&is_b=1)
我们首先观察一下评论,可以发现所有的评论都是匿名的。即使这个用户不是匿名评论的,那也会显示匿名,淘宝这保密做的挺好。
[](http://qiniu.cuiqingcai.com/wp-content/uploads/2016/06/QQ20160630-1@2x.png)
心机的淘宝啊,那我们如果想获取一些旺旺号该咋办?
接下来我们返回宝贝详情页面,然后一直下拉下拉,拉到最最后,可以看到有个“看了又看”板块。
[](http://qiniu.cuiqingcai.com/wp-content/uploads/2016/06/QQ20160630-0@2x.png)
~有没有!!发现了新大陆,这是什么?这是此宝贝相关宝贝以及它的一些评论。~
~看到了有非匿名用户了,哈哈哈,淘宝加密了评论,推荐部分却没有加密。~
~嗯,就从这里,我们把它们的旺旺号都抓下来,顺便把评论和购买的宝贝抓下来。~
现在已经全部改成了匿名,上述话已经无意义了。
那么抓取完之后,保存到哪里呢?为了便于管理和统计,在这里保存到 Excel 中,那么就需要用到 xlrd, xlwt, xlutils 等库。
嗯,动机就是这样。
## 实战爬取
### 抓取过程
首先我们观察这个链接,在最初的时候,其实网页并没有加载最下方的“看了又看”内容的,慢慢往下滑动网页,滑到最下方之后,才发现看了又看页面才慢慢加载出来。
很明显,这个地方使用了Ajax,由于我们用的是 Selenium,所以这里我们不能直接来模拟 Ajax 的 Request,需要我们来模拟真实的用户操作。
所以我们要模拟的就是,在网页部分加载出来之后,模拟浏览器滑动到下方,使“看了又看”内容显示出来,然后获取网页源代码,解析之即可。
那么在这里就出现了两个至关重要的点,一个是判断网页框架大体加载出来,另一个是模拟滑动直到最下方的内容加载出来。
首先,我们解决第一个问题,怎样判断网页框架大体加载出来。我们可以用网页中的某个元素的出现与否来判断。
比如
[](http://qiniu.cuiqingcai.com/wp-content/uploads/2016/06/QQ20160630-2@2x.png)
这一部分是否加载出来。
审查一下代码,ID叫做 J\_TabBarBox,好,那就用它来作为网页初步加载成功的标志。
在 Selenium 中,我们用显式等待的方法来判断该元素是否已经加载成功。
Python
```
try:
driver.get(url)
WebDriverWait(driver, timeout).until(
EC.presence_of_element_located((By.ID, "J_TabBarBox"))
)
except TimeoutException:
return False
if is_recommends_appear(driver, max_scroll_time):
print u'已经成功加载出下方橱窗推荐宝贝信息'
return driver.page_source
```
接下来我们需要模拟下拉浏览器,不妨直接下拉到底部,再从底部向上拉,可能需要下拉多次,所以在这里定义了一个下拉次数,那么判断“看了又看”正文内容是否出现依然可以用显式等待的方法。
浏览器审查元素发现它的选择器是 #J\_TjWaterfall li
[](http://qiniu.cuiqingcai.com/wp-content/uploads/2016/06/QQ20160630-3@2x.png)
那么可以用如下方法来判断是否加载成功
Python
```
try:
driver.find_element_by_css_selector('#J_TjWaterfall li')
except NoSuchElementException:
return False
return True
```
下拉过程可以用执行 JavaScript 的方法实现。
Python
```
js = "window.scrollTo(0,document.body.scrollHeight-" + str(count * count* 200) + ")"
driver.execute_script(js)
```
其中 count 是下拉的次数,经过测试之后,每次拉动距离和 count 是平方关系比较科学,具体不再描述,当然你可以改成自己想要的数值。
嗯,加载出来之后,就可以用
1driver.page_source
来获取网页源代码了
用 pyquery 解析即可。
Python
```
doc = pq(html)
items = doc('#J_TjWaterfall > li')
print u'分析得到下方宝贝中的用户评论:'
for item in items.items():
url = item.find('a').attr('href')
if not url.startswith('http'):
url = 'https:' + url
comments_info = []
comments = item.find('p').items()
for comment in comments:
comment_user = comment.find('b').remove().text()
comment_content = comment.text()
anonymous_str = config.ANONYMOUS_STR
<del>if not anonymous_str in comment_user:</del> #此句本来用来判断是否匿名,现淘宝已修复该漏洞,只能抓取全部匿名的了
comments_info.append((comment_content, comment_user))
info.append({'url': url, 'comments_info': comments_info})
return info
```
然后保存到 Excel 中。
运行结果截图
[](http://qiniu.cuiqingcai.com/wp-content/uploads/2016/06/QQ20160630-7@2x.png)
可以发现,另外提供了先登陆后爬取的功能,然后保存了爬取进度。
### 采集链接
刚才我们测试的链接是哪里来的?我们不能一个个去找吧?所以,在这里又提供了一个采集链接的过程,将采集的链接保存到文本,然后抓取的时候从文本读取一个个链接即可。
所以在这里我们模拟搜索的过程,关键字让用户输入,将搜索的链接采集下来。
在此 Selenium 模拟了输入文字,点击按钮和翻页的功能。
[](http://qiniu.cuiqingcai.com/wp-content/uploads/2016/06/QQ20160630-4@2x.png)
核心代码如下
下面的方法模拟了加载出搜索框之后输入文字点击回车的过程,将网页的结果返回。
Python
```
def get_results(keyword):
driver = config.DRIVER
link = config.SEARCH_LINK
driver.get(link)
try:
WebDriverWait(driver, config.TIMEOUT).until(
EC.presence_of_element_located((By.ID, "mq"))
)
except TimeoutException:
print u'加载页面失败'
try:
element = driver.find_element_by_css_selector('#mq')
print u'成功找到了搜索框'
keyword = keyword.decode('utf-8', 'ignore')
print keyword
print u'输入关键字', keyword
for word in keyword:
print word
element.send_keys(word)
element.send_keys(Keys.ENTER)
except NoSuchElementException:
print u'没有找到搜索框'
print u'正在查询该关键字'
try:
WebDriverWait(driver, config.TIMEOUT).until(
EC.presence_of_element_located((By.CSS_SELECTOR, "#J_ItemList div.productImg-wrap"))
)
except TimeoutException:
print u'查询失败'
html = driver.page_source
return html
```
下面的方法模拟了翻页的过程,到指定的翻页数目为止
Python
```
def get_more_link():
print u'正在采集下一页的宝贝链接'
driver = config.DRIVER
try:
js = "window.scrollTo(0,document.body.scrollHeight)"
driver.execute_script(js)
except WebDriverException:
print u'页面下拉失败'
try:
next = driver.find_element_by_css_selector('#content b.ui-page-num > a.ui-page-next')
next.click()
except NoSuchElementException:
print u'找到了翻页按钮'
driver.implicitly_wait(5)
try:
WebDriverWait(driver, config.TIMEOUT).until(
EC.presence_of_element_located((By.CSS_SELECTOR, "#J_ItemList div.productImg-wrap"))
)
except TimeoutException:
print u'查询失败'
html = driver.page_source
parse_html(html)
```
运行结果截图
[](http://qiniu.cuiqingcai.com/wp-content/uploads/2016/06/QQ20160630-5@2x.png)
采集到到内容保存到 urls.txt 中
[](http://qiniu.cuiqingcai.com/wp-content/uploads/2016/06/QQ20160630-6@2x.png)
嗯,这下采集链接和爬取链接都有了。
## 代码放送
扯了这么多,许多童鞋已经蠢蠢欲动了,大声告诉我你们想要的是什么?
哦没错!代码!
嗯在这呢!
[代码](https://github.com/Germey/TaobaoUser)
## 附加扯淡
嗯想说一句,在这里还提供了一些可配置项,比如翻页最大次数,超时时间,下拉次数,登录链接等等。
都可以在 config.py 中配置。
> * URLS\_FILE
>
> 保存链接单的文件
>
> * OUT\_FILE
>
> 输出文本EXCEL路径
>
> * COUNT\_TXT
>
> 计数文件
>
> * DRIVER
>
> 浏览器驱动
>
> * TIMEOUT
>
> 采集超时时间
>
> * MAX\_SCROLL\_TIME
>
> 下拉滚动条最大次数
>
> * NOW\_URL\_COUNT
>
> 当前采集到第几个链接
>
> * LOGIN\_URL
>
> 登录淘宝的链接
>
> * SEARCH\_LINK
>
> 采集淘宝链接搜索页面
>
> * CONTENT
>
> 采集链接临时变量
>
> * PAGE
>
> 采集淘宝链接翻页数目
>
> * FILTER\_SHOP
>
> 是否过滤相同店铺
>
> * ~ANONYMOUS\_STR~
>
> ~匿名用户标志,已失效~
- LINUX命令
- 用户组和用户管理
- Linux文件共享服务
- Linux服务软件
- 网络管理
- ping不通
- Linux防火墙
- 解压缩
- vim编辑器
- GIT服务器
- GitLab
- 文件和目录命令
- 文件权限
- 文件属性
- 端口管理
- LInux基本命令
- ll
- screen命令
- sh 脚本
- 基本操作
- 磁盘管理
- vmware 磁盘扩容
- 基本目录介绍
- 调整分区
- 查看磁盘大小
- 统计文件大小
- 关机、重启
- 定时任务
- 定时任务排查
- 按秒执行脚本
- 执行php请求
- 环境变量
- 把php加入到环境变量
- 系统时间操作
- 进程管理
- CPU 管理
- TOP命令简介
- ps 命令介绍
- ps使用实例
- 报错管理
- ifconfig 报错
- fuser 报错
- 内存管理
- 查看内存
- PHP
- 函数管理
- Curl请求
- 加密函数
- 闭包函数
- php自定义函数
- 获取字符串首字母生成图片
- 字符串处理
- 隐藏部分字符串
- 字符串编码格式
- GB2312编码
- ASCII码介绍
- 随机生成汉字
- 编码转换函数
- 获取字符串首字母
- 全半角转换
- 字符串加、解密
- 字符串截取
- 数组处理
- 控制抽奖概率
- 二维数组转化为字符串
- 获取数组中最后一个元素
- 数组去重
- 数组排序
- 插件管理
- TCPDF
- PHP扩展
- Redis扩展
- TP5中使用Redis
- redis 服务不能开启
- CURl
- 魔术方法
- 系统函数
- PHP规范
- PSR-4
- 个人规范
- 数据表规范
- 系统常量、变量
- 常量PHP_SAPI与函数php_sapi_name()
- 进制转换
- ThinkPHP
- TP5.0
- 发送邮件
- TP5.1
- 控制器
- composer类库
- 通过json格式实现三级联动
- 查询语法
- model 模型
- PSR规范
- 导入导出
- CSV导出
- 文件目录操作
- 递归创建目录
- 文件大小单位转换
- 微信小程序
- 小程序支付
- 打印输出
- 日志操作
- 数据类型转换
- 数组转XML格式
- XML转数组
- 时间日期
- 计算时间差值的函数
- 计算程序运行时间
- 图片处理
- 图片压缩类
- Mysql
- 字段类型介绍
- 安装配置
- 数据库操作
- 数据表
- 查看创建表
- 创建表
- 插入数据
- 修改表
- 删除表
- 查询
- 时间查询
- 表的高级操作
- 视图
- 触发器
- 存储过程
- 事务
- 索引
- 存储引擎
- 数据库优化
- mysql中使用 where 1=1和 0=1 的作用
- 在线修改字段禁忌
- mysql配置文件
- mysql8.0新特性
- 数据库引擎
- Mysql 内置函数
- GROUP BY
- group_concat 函数的限制
- 远程连接
- 远程无法连接
- mysql远程连接问题
- mysql 导入导出
- mysql日志处理
- 性能优化
- Yaconf-高性能的配置管理扩展
- FTP上传opcache缓存
- 系统内置函数注意事项
- in_array()
- 并发和攻击
- sql防注入
- 防范csrf攻击
- XSS处理
- DDOS攻击和防范
- 日常报错
- 文件访问权限
- 专业术语
- PV、 UV、IP
- TPS、QPS、RT
- 安全配置
- 安全模式
- 报错处理
- open_basedir 报错
- PHP异常报错
- 类
- new static() 和 new self()区别
- 接口
- static::$val()和self::$val()介绍
- PHP中静态方法和实例化方法的区别
- 抽象类
- PHP函数include include_once require和require_once的区别
- final 关键字
- 内置迭代器类
- 命名空间和spl_autoload_register函数
- 修改类的私有成员属性
- php closure 的bind和bindTo
- trait 类
- php 正则
- php 正则函数
- 小案例
- foreach遍历数组
- 设计模式
- 单例模式
- 简单工厂模式
- 工厂模式
- 抽象工厂方法设计模式
- 使用简单工厂来优化抽象工厂模式
- 使用反射来优化抽象工厂模式
- 原型模式
- 适配器模式
- 对象适配器模式
- 桥接设计模式
- 装饰设计模式
- 组合设计模式
- 透明组合设计模式
- 安全组合设计模式
- 外观设计模式
- 享元设计模式
- 代理设计模式
- 模板设计模式
- 命令设计模式
- 迭代器设计模式
- 观察者设计模式
- 单元测试框架
- PHPUnit_Framework_TestCase
- Windowns
- 用户凭证
- 命令
- 设置电脑自动关机
- win文件共享
- excel表多人同时编辑
- 文件共享打开只读
- win 网络管理
- 电脑连接不上网络
- 法自动获取IP地址
- win10 进入安全模式
- 虚拟机
- vmware esxi集群
- Python
- 头部介绍
- 开始 工作
- 内置函数
- bytes
- 数据类型
- 位运算
- 字符串类型
- 清除空格或者填充
- 随机数
- 字符串编码
- python3 编码
- 判断是否为空,为None等
- 列表、元组、字典
- 数据处理
- 时间日期处理
- 获取下一个星期几
- 月份处理
- 函数
- 获取本地IP
- 判断当前是否可以联网
- 模块
- argparse 模块
- cookielib 模块
- urllib 爬虫模块
- types 模块
- subprocess 爬虫模块
- requests 爬虫模块
- Beautiful Soup 爬虫模块
- Xpath 爬虫模块与lxml 爬虫模块
- PhantomJS 爬虫模块
- xlrd 模块
- xlwt 模块
- 模块安装
- ssl 模块
- json 模块
- configparser 模块
- 文件操作
- 异常处理
- 面向对象
- 正则
- Mysql数据库
- Socket
- Sublime
- 数学
- 实例
- py进制转换
- 画图
- 画布详解
- 爬虫
- Python2爬取糗事百科段子
- Python2爬取百度贴吧
- python2无线网络掉线自动重连
- Python2抓取淘宝MM照片
- python2模拟登录淘宝并获取所有订单
- python2抓取爱问知识人问题并保存至数据库
- python2利用Selenium抓取淘宝匿名旺旺
- python2爬虫专用模块
- urllib 模块
- subprocess 模块
- requests 模块
- Beautiful Soup 模块
- Xpath 模块与lxml 模块
- PhantomJS 工具
- Selenium 工具
- PyQuery 工具
- 爬虫框架介绍
- PySpider 框架安装配置
- PySpider 的用法
- Scrapy 框架安装配置
- 爬虫之多进程和多线程
- 爬虫之多线程用法
- 爬虫之多进程用法
- 服务器代理
- python2
- python3
- 编辑器
- sublime
- 插件介绍
- Visual Studio Code
- 前端
- js或jquery初始化
- Vue
- 目录结构
- 环境搭建、安装
- 模块介绍与安装
- vue-axios + axios
- vuex
- vant-ui
- less
- vue 方法属性
- 前端字符串处理
- 字符串反转
- CSS
- 文本显示问题
- Jquery
- 遍历json对象
- ajax
- 获取节点
- select 操作
- 自定义函数
- in_array()
- 事件
- input事件
- 数组基本操作
- js判断是否为空
- js判断数组是否存在某个值
- 判断是否是数组
- js中json对象和字符串的转换
- 去重,过滤空数组
- 字符串基本操作
- 判断变量是否定义
- js时间日期
- 日期格式转时间戳
- Nginx
- nginx配置参数
- HTTP协议
- HTTP头部信息
- 浏览器缓存
- Content-Type类型介绍
- Content-transfer-encoding类型介绍