老司机教你用Python爬大众点评(上期) 您所在的位置:网站首页 点评app是什么意思 老司机教你用Python爬大众点评(上期)

老司机教你用Python爬大众点评(上期)

2024-04-20 13:28| 来源: 网络整理| 查看: 265

前言

近期,从Boss那里领取了一份爬数据的任务,刚开始接到任务的时候,感觉应该很简单,页面是静态页面,不用js渲染,也不用自己构造请求参数,就是个从网页文本中用标签选择器咔咔一顿乱选,最后整理存入mongoDB即可,导出csv,完成任务。这本来是我心目中完美的一套流程,但是,随着更加深入的进入到工作节奏中之后,我才发现事情并没有那么简单~~~(大众点评的前端,你真可爱)

前期准备

古人云:工欲善其事,必先利其器。一般网络爬虫,比较经典的几个库是必须的,例如:lxml、 requests、 BeautifulSoup,先甭说其他的,先装吧

pip3 install lxml pip3 install requests pip3 install beautifulsoup4

在准备好我们的利器之后,接下来肯定就是开始搞事情~~~

开搞第一波

熟练的在浏览器中输入 http://www.dianping.com,然后随便打开一个店,比如这个

熟练的点击登录,拿手机扫码登录,出现上图~~~ 随着下拉页面,我们终于看到了我们所需要的评论数据,比如这样:

来,摁一下F12,右击检查来瞧瞧这些可爱的小宝贝,到底在html里面是怎么存在的,此时发出了志在必得的嘲笑声~~~哈哈哈哈哈 然后~~~

这是什么??此刻黑人问号脸??在页面上不是显示是字吗?这个 svgmtsi是什么标签,我的网页设计白学了?我记着我当时学习挺认真的啊?大兵老师教的挺好呀????????????

第一次尝试,失败!Game Over!

第二次尝试

在进行第一次尝试之后,发现大众点评这个网站并不是用普通方式渲染的,是用特定的标签进行渲染上去的,这个标签到底是什么呢?让我很是费解,从来没见过,我该如何下手?既然是不认识的东西,那么看看它的属性?在CSS是怎样表示的。

看了一下这个标签,在CSS中只有一个 background属性,给了两个坐标,难道字是用图片拼的?带着怀疑的心情,看一看这个 background究竟是何方神圣,打开那个url一看,是这样的情况:

看到了这一个个熟悉的字,果然是通过图片渲染到页面上的,但是,另外一个难题出现了,这个字究竟是怎么对应上去的,此时还有一个信息没有用,那就是上面CSS发现的坐标值,看一看这个svg的源码吧,看看有没有什么发现,打开源码,是这样的~~~

看到了,x和y的值,是不是跟上面的 background有一定的关系,此时发挥出小时候做找规律数学题的技能,找一找规律~~~

我们来看一下 年这个字的坐标:-434、 -1512,在svg源码中搜索这个字

年字在这一行中是第32个字,同时这一样的y坐标是1535,在CSS中它的属性y坐标是-1512,如果将坐标取正值,正式坐标差23,推测一下,y坐标计算是通过background属性y取正加23得到,我们验证一下其他字,发现也是这个规律,至此,我们推测出,y坐标的对应关系;现在还剩下最后一个难题,x的坐标该怎么对应?此时发现svg上面有这么一个属性:

字号是14px,是不是字数*14就等于x坐标了呢?求证一下,年是第32个字,但是31 * 14 = 434,所以大胆猜测一下,x坐标是这个字在这一行的(第几位-1)* 14所得,后来发现其他字也是这样,推测正确。 第二次尝试~~~成功!

获得结论

每个标签的background属性对应着svg中的位置,首先计算过程是将x、y取正,用x / 14 所得的值+1,就是这个标签所代表字在这一行的第几位,用 y + 23 就是带这个标签代表字在哪一行

获取网页源码

接下来要做的,就是通过正常的get请求,去获取评论页的源码,在经过几次的尝试之后,发现这么一个问题,每次请求如果用一个请求头的话,最多你只能拿到30页左右的评论数据,在想继续拿到就会被封锁,即使你传入Cookie值,也无济于事

所以你需要使用一个第三方的库:fake_useragent

pip3 install fake_useragent

使用示例:

from fake_useragent import UserAgent ua = UserAgent(verify_ssl=False) ua.random #这里会生成一个随机的浏览器请求头

第二步,在收集网页数据的过程中,每次请求的间隔不要太短,每次请求的过程中还可能触发验证机制,你需要在浏览器端进行手动验证,方可继续使用访问,每次请求评论页的Referer是上一页的网址,意思就是告诉大众点评,你是一页一页评论连续看的,并不是从第一页一直调到其他页,下面放一下源码:

get_data.py

import requests import time import re import sys from fake_useragent import UserAgent ua = UserAgent(verify_ssl=False) url = 'http://www.dianping.com/shop/' + sys.argv[1] + '/review_all' for i in range(2, int(sys.argv[2])): headers = { 'User-Agent': ua.random, 'Referer': url + '/p' + str(i-1), 'Cookie': sys.argv[3] } u = url + '/p' + str(i) result = requests.get(u, headers=headers).text a = re.findall('

抱歉!页面无法访问......

', result, re.S) b = re.findall("验证中心", result, re.S) if a: print('IP被封,死心了吧') temp = input() elif b: print('去浏览器进行手工验证') temp = input() else: with open(str(i)+ '.html', 'w', encoding='utf-8') as file: file.write(result) print(u + '已经下载完毕') time.sleep(5)

在使用get_data.py的时候需要传入三个参数,第一个是你要爬取的店铺的id,在网址中也可以看到,例如这个:

第二个参数,是你要爬到第几页

第三个参数,是你从浏览器中复制的Cookie

开始爬取

代码流程如下:

读取网页源码--->从源码中获取CSS文件URL--->从CSS文件中获取到SVG文件的URL--->获取SVG的内容--->选取评论标签--->解析标签SVG的URL--->解析标签的class--->获取坐标--->从SVG中对应字--->保存数据

在这里贴出来几个关键函数:

def get_Word_Point(className, CSSContent): point = re.findall(className + '{background:-(.*?).0px.*?-(.*?).0px', CSSContent, re.S) x = int(int(point[0][0])/14) y = int(point[0][1]) + 23 return x, y def get_Word_Content(SVGUrl, x, y, SVG_dic): SVGContent = SVG_dic[SVGUrl] result = re.findall('(.*?)', SVGContent, re.S) if result: return result[0][x] else: return get_Word_Content_B(SVGUrl, x, y, SVG_dic) 结果展示Tips

在与大众点评斗志斗勇的过程中,发现大众点评的CSS加密机制是一天两换的,上面的那个加密机制只是白天的一种,如果你访问频率过多,大众点评会自动触发另外一套加密机制,另外一套加密机制将会在下期进行述说,敬请期待。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有