大众点评还不会爬?学好Python带你各种爬

今天的文章是关于如何使用requests来爬取大众点评的数据。

看完本文,你可以:

1、了解大众点评的CSS反爬虫机制

2、破解反爬虫机制

3、使用requests即可正确获取到评论数,平均价格,服务,味道,环境数据,评论文本数据;

同时,代码我并**没有做太多的优化,因为没有大量的代理,爬不了太多的内容。

这里只是跟大家分享一下处理的流程

正文开始。

大众点评还不会爬?学好Python带你各种爬

1.前言

在工作生活中,发现越来越多的人对大众点评的数据感兴趣,而大众点评的反爬又是比较严格的。采取的策略差不多是宁可错杀一万,也不放过一个。有的时候正常浏览都会跳出验证码。

另外,在PC端的展示数据是通过CSS来控制的,从网页上看不出来太大的区别,但是用普通的脚本取获取时,会发现数据是获取不到的,具体的源代码是下面这样的:

大众点评还不会爬?学好Python带你各种爬

然,在搜资料的时候,你会发现,很多教程都是用的selenium之类的方法,效率太低,没有啥技术含量。

所以,这篇文章的面向的对象就是PC端的大众点评;目标是解决这种反爬虫措施,使用requests获取到干净正确的数据;

跟着我,绝不会让你失望。

如果你依然在编程的世界里迷茫,可以加入我们的Python学习扣qun:784758214,看看前辈们是如何学习的。交流经验。从基础的python脚本到web开发、爬虫、django、数据挖掘等,零基础到项目实战的资料都有整理。送给每一位python的小伙伴!分享一些学习的方法和需要注意的小细节,点击加入我们的 python学习者聚集地

大众点评还不会爬?学好Python带你各种爬

2.正文开始

相信搞过大众点评网站的同学都应该知道上面的这种是一个css反爬的方法,具体的解析操作,即将开始。

找到藏着秘密的css

当我们的鼠标在上面框框内的span上面点击时,会发现右边部分会相应的发生变化:

大众点评还不会爬?学好Python带你各种爬

这张图片很重要,很重要,很重要,我们要的值,几乎都从这里匹配出来。

这里我们看到了“vxt20”这个变量对应的两个像素值,前面的是控制用哪个数字,后面的是控制用哪一段的数字集合,先记下,后面要用,同时这里的值应该是6;

这里其实就是整个破解流程最关键的一步了。在这里我们看到了一个链接。

瞎猫当死耗子吧,点进去看看。

https://s3plus.meituan.net/v1/mss_0a06a471f9514fc79c981b5466f56b91/svgtextcss/f556c0559161832a4c6192e097db3dc2.svg

你会发现,返回的是一些数字,我一开始是不知道这是啥玩意的,看过一些大神的解析才知道,其实这里就是我们看到的数字的来源,也就是整个破解的源头,知道了这些数字的含义,也就可以直接破解了整个反爬的流程。

现在直接看源代码:

大众点评还不会爬?学好Python带你各种爬

可以看到这里面的几个关键数字:font-size:字体大小;还有几个y的值,我到后面才知道原来这个y是个阈值,起的是个控制的作用。

所以,这一反爬的原理就是:

获取属性值与偏移量和阈值映射,然后从svg文件中找到真数据。

现在我们就要用到上面的像素值了。

1.把所有的值取绝对值;

2.用后面的值来选择用哪个段的数字,这里的值是103,所以使用第三个段的数字集合;

3.因为每个字体是12个像素,所以用163/12=13.58,约等于14,那么我们数一下第14个数字是啥,没错,是6,和预期一样。你可以多试验几次。

以上,就是整个破解的逻辑过程。

画个流程图,装个逼:

大众点评还不会爬?学好Python带你各种爬

3.Show Code

下面开始晒代码,俗话说得好,天下代码一大抄。

大众点评还不会爬?学好Python带你各种爬

这里对主要的步骤代码进行解释, 如果你想获取更多的代码,请关注我的公众号,并发送 “大众点评”即可。

1.获取css_url及span对应的TAG值;


def get_tag(_list,  offset=1):

    # 从第一个开始查

    _new_list  =  [data[0:offset]  for  data in  _list]

    if  len(set(_new_list))  ==  1:

        # 如果set后只有一个值,说明全部重复,这个时候就把offset加1

        offset  +=  1

        return  get_tag(_list,  offset)

    else:

        _return_data  =  [data[0:offset  -  1]  for  data in  _list][0]

        return  _return_data

def get_css_and_tag(content):

    """

    :param url: 待爬链接

    :return: css链接,该span对应的tag

    """

    find_css_url  =  re.search(r'href="([^"]+svgtextcss[^"]+)"',  content,  re.M)

    if  not  find_css_url:

        raise Exception("cannot find css_url ,check")

    css_url  =  find_css_url.group(1)

    css_url  =  "https:"  +  css_url

    # 这个网页上不同的字段是由不同的css段来进行控制的,所以要找到这个评论数据对应的tag,在这里返回的值为vx;而在获取评论数据时,tag就是fu-;

    # 具体可以观察上面截图的3个span对应的属性值,相等的最长部分为vx

    class_tag  =  re.findall("<b class=\"(.*?)\"></b>",  content)

    _tag  =  get_tag(class_tag)

    return  css_url,  _tag

2.获取属性与像素值的对应关系

def get_css_and_px_dict(css_url):

    con  =  requests.get(css_url,  headers=headers).content.decode("utf-8")

    find_datas  =  re.findall(r'(\.[a-zA-Z0-9-]+)\{background:(\-\d+\.\d+)px (\-\d+\.\d+)px',  con)

    css_name_and_px  =  {}

    for  data in  find_datas:

        # 属性对应的值

        span_class_attr_name=  data[0][1:]

        # 偏移量

        offset  =  data[1]

        # 阈值

        position  =  data[2]

        css_name_and_px[span_class_attr_name]  =  [offset,  position]

    return  css_name_and_px

3.获取svg文件的url


def get_svg_threshold_and_int_dict(css_url,  _tag):

    con  =  requests.get(css_url,  headers=headers).content.decode("utf-8")

    index_and_word_dict  =  {}

    # 根据tag值匹配到相应的svg的网址

    find_svg_url  =  re.search(r'span\[class\^="%s"\].*?background\-image: url\((.*?)\);'  %  _tag,  con)

    if  not  find_svg_url:

        raise Exception("cannot find svg file, check")

    svg_url  =  find_svg_url.group(1)

    svg_url  =  "https:"  +  svg_url

    svg_content  =  requests.get(svg_url,  headers=headers).content

    root  =  H.document_fromstring(svg_content)

    datas  =  root.xpath("//text")

    # 把阈值和对应的数字集合放入一个字典中

    last  =  0

    for  index,  data in  enumerate(datas):

        y  =  int(data.xpath('@y')[0])

        int_data  =  data.xpath('text()')[0]

        index_and_word_dict[int_data]  =  range(last,  y+1)

        last  =  y

    return  index_and_word_dict

4. 获取最终的值


在学习过程中有什么不懂得可以加我的
python学习交流扣扣qun,784758214
群里有不错的学习视频教程、开发工具与电子书籍。
与你分享python企业当下人才需求及怎么从零基础学习好python,和学习什么内容

def get_data(url  ):

    """

    :param page_url: 待获取url

    :return:

    """

    con  =  requests.get(url,  headers=headers).content.decode("utf-8")

    # 获取css url,及tag

    css_url,  _tag  =  get_css(con)

    # 获取css对应名与像素的映射

    css_and_px_dict  =  get_css_and_px_dict(css_url)

    # 获取svg的阈值与数字集合的映射

    svg_threshold_and_int_dict  =  get_svg_threshold_and_int_dict(css_url,  _tag)

    doc  =  etree.HTML(con)

    shops  =  doc.xpath('//div[@id="shop-all-list"]/ul/li')

    for  shop in  shops:

        # 店名

        name  =  shop.xpath('.//div[@class="tit"]/a')[0].attrib["title"]

        print name

        comment_num  =  0

        comment_and_price_datas  =  shop.xpath('.//div[@class="comment"]')

        for  comment_and_price_data in  comment_and_price_datas:

            _comment_data  =  comment_and_price_data.xpath('a[@class="review-num"]/b/node()')

            # 遍历每一个node,这里node的类型不同,分别有etree._ElementStringResult(字符),etree._Element(元素),etree._ElementUnicodeResult(字符)

            for  _node in  _comment_data:

                # 如果是字符,则直接取出

                if  isinstance(_node,  etree._ElementStringResult):

                    comment_num  =  comment_num *  10  +  int(_node)

                else:

                    # 如果是span类型,则要去找数据

                    # span class的attr

                    span_class_attr_name  =  _node.attrib["class"]

                    # 偏移量,以及所处的段

                    offset,  position  =  css_and_px_dict[span_class_attr_name]

                    index  =  abs(int(float(offset)  ))

                    position  =  abs(int(float(position)))

                    # 判断

                    for  key,  value in  svg_threshold_and_int_dict.iteritems():

                        if  position in  value:

                            threshold  =  int(math.ceil(index/12))

                            number  =  int(key[threshold])

                            comment_num  =  comment_num *  10  +  number

            print comment_num

4.结果展示

评论条数数据

其实,其他的我都写好了,就不贴了

大众点评还不会爬?学好Python带你各种爬

大众点评还不会爬?学好Python带你各种爬

评论具体数据

大众点评还不会爬?学好Python带你各种爬

大众点评还不会爬?学好Python带你各种爬

5.结语

以上就是大众点评Css反爬破解的全部步骤和部分代码。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值