爬取京东《刻意练习》图书评论并生成图词
前言:
本文主要为爬虫入门篇,通过简单的 requests 模块,爬取京东销售的图书《刻意练习》的评论,并生成云图词,体验爬虫的小乐趣。
实现的目的
《刻意练习》这本书是一本非常棒的书,作者通过长时间的观察和亲身实践,研究和讲述学习的过程,以及从新手到大师 master 的必经之路,和刻意练习之方法。
如果非常喜欢这本书,想看一下买这本书的人对于这本书的评价是什么样的,当然可以自己去看评论区,但是只能草略的看,想全面的评论统计,那么就需要爬虫出马了。
通过爬虫可以快速地,大量地爬取到有关这本图书的几乎所有的评论,然后统计所有评论中的关键词,生成词图,达到我们快速了解购买这本书的读者的评价的目的。
上手
首先,我们需要打开京东关于这本书的评论,这很简单,用浏览器我们可以办得到(推荐使用 Chrome 浏览器,可能会更加方便)
我们点击中间的商品评价,所有的评论便都在下面了。
第一行代码
本次爬取数据,使用的是 Python 的一个库——Requests,在这里我们只需要明白它是一个特别强大的库就可以了,如果想要了解更多关于Requests的内容,我们只需要用搜索引擎搜索它,然后详细仔细的查看和研究,本文我们变用变学习Requests 的功能。
导入 Requests 库
1 | import requests |
上面这第一行代码意思是将Requests库导入当前python文件,只有导入后才能使用(Python 有很多的库文件,我们用哪个就需要提前导入哪个)
定义评论链接
1 | url = "https://sclub.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98vv2783&productId=11990777&score=0&sortType=5&page=0&pageSize=10&isShadowSku=0&rid=0&fold=1" |
这段代码定义一个 url 变量,并将评论链接赋值给url这个变量,但是这个评论链接是从哪里找到的呢?有了这个疑问,这也是本次教程最重要的部分。
找到评论链接
要想获得所有评论,我们要有一个概念,1. 其实评论肯定都存储在京东的服务器上,2. 当我们点击评论的时候,浏览器向服务器索要评论内容,3. 服务器会给出一个评论链接,4. 浏览器通过这个评论链接便能查看所有的评论
好,我们可以理解为,有一条线,这条线牵引着所有的评论内容。接下来我们的目的就是找到这条线。
打开浏览器开发模式
按 F12(或者 fn键+F12),再或者在评论区的当前页面 右击 然后点击 检查(inspect) 选项,开发者模式就被我们调出来了。具体如下图:
出现这个之后一定要先做一件事情:点击下图标号1,开发者框中的「Network」按钮,然后再将页面进行刷新(按 F5,或者如图点击标号2的刷新图标)如下图:
想要找到评论我们需要全文搜索评论元素,当然不要忘记了,用过 Word我们肯定知道,Control键+F 是可以全文进行搜索的,在这里当然也管用。
我们试一下:先复制第一条评论“非常不错啊!有理论,更有实践,没节都有些tips可以使用。真好。强烈推荐。”
然后点击一下开发者区域(也就是我们之前按 F12 之后出现的区域),按下 Control + F(Mac 下面是 Command + F),会在左边出现一个搜索框:我们将复制的评论粘贴在搜索框中,并按下回车键
我们点击搜索出现的第一条内容,如上图箭头所指示,会在右边出现下面的内容:
我们的目的是要找链接,观察到有一个headers,没错,链接就藏在里面,点击查看:
我们稍微简单解释一下几条信息:
Request URL:URL代表的是Uniform Resource Locator,统一资源定位符,它是WWW的统一资源定位标志,就是指网络地址。比如说“www.baidu.com”这就是一个 URL。
那很显然了,这个URL请求的链接就是服务器返回给浏览器的评论的链接。
Request Method:GET,这个代表的是 Request 这个请求的方法。如果我们搜索 Request 这个关键词,就会发现 Request 其实是客户端用来发送请求的一个对象,而 Request 对象有好几种方法,GET 是其中一种,Request 利用这些方法向服务器发送请求。
这个在这里不重要,简单了解即可。
Status Code:200。字面含义就很清楚了,状态编码,我们用200来代表,请求成功,当然,还有一些其他的编码,比如我们所熟悉的 404 网页不存在,或者不到网页(如果你没有碰到过404的话,没关系,你可以在浏览器中输入”www.google.com”,404就会出现的)
真正的开始
别忘了,我们的主要目的是干什么——找到评论链接,事实上我们已经找到了,就在上面的 Request URL中,我们不妨复制下来看看它有什么特征
嚯,这实在是太难了,如果我们之前从没有接触过的话,我们几乎不可能看出它有什么重要特征。
不要紧,事实上,这只是第一个评论页面的链接,我们不妨再找一下第二页评论的链接,然后我们来找区别,这样就会有一些特征出现。
第二页评论:我们先点击评论的数字 2
然后按照上面所说的方法,复制当前页面的第一个评论,然后去开发者页面中的搜索框中搜索,然后点击出现的第一条内容,然后再在右边查看 headers 中的 Request URL 的内容,第二个链接:
好了,开始找不同,我们用文本对比网页(搜索引擎搜索“文本对比”即可出现相关链接)会很快发现,有一个明显的异同点:
为什么是 0 和 1 呢?如果我们再看第三页会怎样呢?
事实上,当第三页,这个二者有不同的地方就变成了数字2,好了,这一切都联系起来了。从 0 开始代表了第一页,之后每增加一页,数字加1。
知道了上面这些,意味着我们可以真正开始大量爬取评论数据了。
爬取第一页评论
1 | import requests |
上面我们定义了一个函数comment_spider( ) ,这个函数里面的URL是我们上面费力找到的。
然后,我们通过使用try,尝试对URL进行数据爬取:
1 | r = requests.get(url) |
这是我们利用Requests发起一个GET请求,并把请求到的数据赋值给r。
1 | print(r.status_code) |
我们利用r.status_code来查看,请求内容是否成功,我们在之前说过,如果返回200,代表请求成功,如果返回404,证明访问的内容不存在。当然,还有可能返回到其他的编码,但我们想要的显然是 200
如果try语句之后的内容执行失败,我们就会执行except后面的内容。
1 | if __name__ == '__main__': |
上面的代码,即为一个主函数执行函数入口,在主函数里我们执行编写的comment__spider() 函数
执行一下看一下
可以看到,返回 200 访问成功的状态编码,意味着我们的URL访问没有问题,但是为什么没有任何的评论数据显示呢?
事实上,这是我们请求的时候,服务器核验我们出了差错,这是基础的反爬虫措施,我们返回开发者页面,进行查看。
有一个Requests Headers,这是一个请求头,我们需要在利用requests.get方法发起请求的时候,把这个请求头加上,这样服务器就能够正常返回我们想要的内容。
我们需要设置一个字典:
1 | kv = {'user-agent': 'Mozilla/5.0','Referer':'https://item.jd.com/11990777.html'} |
这里面包含的user-agent代表发起请求的浏览器信息,Refeer用于标识请求的来源
然后我们修改requests.get请求,把我们的请求头加上:
1 | r = requests.get(url,headers = kv) |
完整代码:
1 |
|
可以看到打印的内容,我们可以获取到想要的想要的评论数据。
值得一提的小细节
我们通过查看打印内容,真正的JSON数据是{ }里面的内容,也就是,去掉前面的“fetchJSON_comment98vv2783( “ 和 后面的 “); “ 的内容。
我们用切片的方法,来获取这段JSON数据。
1 | r_json_str = r.text[26:-2] |
这段代码定义一个 r_json_str 的变量,其中[26:-2] 表示将r.text 内容的第26个到倒数第2个字符切下来。
数据分析与提取
我们上面获得到的数据,其实是JSON数据,至于JSON是什么,我们现在只需要知道,它是一种数据交换格式,可以用来传递一些数据。
我们通过开发者模式中的Preview便可以稍微查看一下有什么数据,也可以百度搜索 JSON解析链接后,将 JSON 数据粘贴进去查看解析数据。
这里我们利用 Chrome 的 Preview 功能查看一下。
可以发现有一个comment,这个数据其实是一个字典格式。
python 有一个库,可以方便的查看字典格式,将整个层次分割开来。
我们先利用 import 导入这个库
1 | import pprint |
然后下面的代码可以查看 JSON 解析数据字典格式的层次结构
1 | data = json.loads(r.text[26:-2]) |
完整代码:
1 | import requests |
打印出的字典结构:
可以看到评论内容存在content对象中,所以我们只需要循环出所有 comments 中的 content 对象中内容,就能将所有的评论取出来。
然后我们尝试把评论打印出来
完整代码:
1 |
|
翻页处理,打印多页评论
值得注意的是,我们上面只能打印出第一页的评论数据,这是因为我们的 URL 链接只是第一页的数据链接。
但我们前面已经分析过每个页码的 URL 差别其实就是 page=0 这个地方的不同,如下图:
所以我们只需要修改有差别的地方,便可以获取多页的数据。
怎样修改呢?
首先改造一下 comment_spider 函数,使其拥有一个默认参数 page = 0,也就是默认情况下爬取第1页内容,但为什么是数字0呢?这是因为编程习惯上使用0作为开始的下标。
上面这段代码,还包含一个 数据保存 的功能,其中的 FILE_PATH 就是文件路径,我们需要在开头的位置提前定义一下:
1 | FILE_PATH = 'book_comments.txt' |
然后,我们重复执行这个函数,每次将其参数 page 进行 +1 操作,就可以实现爬取多页数据,怎样实现这个重复呢?对,我们可以再定义一个函数来执行它啊!
我们定义 loop_spider() 函数来重复执行 comment_spider(page = 0) 这个函数,这样就达到目的了。
在这里我们首先用 python 的 OS 模块进行判断文件是否存在,如果存在先删除掉。然后再利用 for 循环执行 comment_spider(page = 0) 这个函数。在这里我们先执行10次。
还注意到,我们使用了 time 这个 python 库,这一行代码是用来进行延时处理的,这样做的目的是为了不让我们的爬虫操作太频繁,而被系统封掉 IP
完整代码:
1 | import os |
这样一来,我们就能获取到很多评论数据,默认爬取10页评论,如果想要爬取更多,更改 loop_spider() 函数中的参数就能实现我们想要爬取的页数,比如改为50页:只需修改最后的主函数 loop_spider() 为 loop_spider(50)
生成云词
生成云词我们定义两个函数,一个是用来获取,评论内容,并进行分词处理;另一个用来生成云词。
其中我们需要设置两个参数
1 | WC_MASK_IMG = 'ky.jpg' #云词的背景图片 |
最终的完整代码:
1 | import os |
生成的效果:
我们就可以看到评论里最多的词语,进而可以有一个对这本书大致的分析判断。