python

大眾點評爬蟲

python爬蟲——大眾點評svg反爬(僅供學習使用)

學爬蟲有大半年,僅僅會一些基礎的爬蟲,對一些反爬有深度的反爬就over了,最近在學svg反爬字型反爬,然後用大眾點評練一下。當然會有程式碼跑起來效率不高的的地方以及錯誤,大家可以指點。

前言

大眾點評是一款非常受大眾喜愛的一個第三方的美食相關的點評網站。從網站內可以推薦吃喝玩樂優惠資訊,提供美食餐廳、酒店旅遊、電影票、家居裝修、美容美髮、運動健身等各類生活服務,透過海量真實消費評論的聚合,幫助大家選到服務滿意商家。因此,該網站的資料也就非常有價值。優惠,評價數量,好評度等資料也就非常受資料公司的歡迎。


1.分析

圖片1
在這裡插入圖片描述

我們可以看到我所畫紅色圈圈的地方,評論有些被遮擋了,不顯示,怎麼辦,很氣人,要放棄嗎?不可能的。然後我就問了一下度娘,她說在藍色圈圈那個曲線處,這時我們選中程式碼,也就是黑色線處,然後右擊藍色線處的,然後open in new tab,然後開啟下面這個頁面。當然我們也要copy這個連結,在網頁程式碼中搜索(ctrl+F),會發現找不到,我們把 ‘http:’去掉
搜尋會找到的。到時我們可以xpath到。
圖片2
在這裡插入圖片描述
然後我用谷歌外掛美化一下,變成下面模樣,感覺看著很舒服
圖片3
在這裡插入圖片描述
background: -num1 px -num2px.我們可以發現num1都是14倍數(一個漢字的寬度,在圖片1中藍色圈中可以看到 width : 14px,有可能與x相關;’num2很有可能是y,但是不一定是y值,是y周圍的數,我們可以找到特定規律找到y值。

同時我們可以看第一張圖片裡面網頁程式碼,與評論有關的標籤都是svgmtsi所以在我們美化的css程式碼頁面(也就是第三張),先ctrl+F一下進行搜尋,果然找到了它,並且還有連結,哎呦,不錯呀,心中小喜。我們把連結複製一下,在前面加http:,然後變成這個模樣==》http://s3plus.meituan.net/v1/mss_0a06a471f9514fc79c981b5466f56b91/svgtextcss/8379576b648e1338a56600ef56fbb993.svg,我們開啟它,是下面這個樣子。
圖片4
在這裡插入圖片描述
我們來開一下網頁程式碼
圖片5
在這裡插入圖片描述
圖片6
在這裡插入圖片描述
圖片5,6中網頁程式碼中標籤defs的子標籤path與標籤text的子標籤textPath數量都一樣都是1-81。我們可以猜測這兩者有關係,並且textPath中的textLength等於的數字是14,那該數字除以14有可能是代表漢字的橫座標x。我們繼續分析,在標籤text中d=“M0 num H600”(num代表裡面的數字),我們用num減去23恰好等於num2,所以我找了多個漢字進行試驗,確實是。
我們來順一下思路:
num/14代表x,num2+23也就是y為svg原始碼path標籤中id數或者textPath標籤href中去#號的數,我們先定位y,然後在定位x,就能找到我們svg對映關係,可以用字典表示。
下面上程式碼,我們試試。

2.引入庫

requests庫相對於urllib3庫是非常強大的,驗證了那句青出於藍而勝於藍;lxml庫在這裡主要用於xpath;re當然是強大的正則了,我以前爬蟲是主要是xpath,正則是真的不行,然後為了svg,我狠狠的補了一把re。

import requests
from lxml import etree
import re

3.開始爬取:

我們先得到css的url,

#得到css url
url = 'http://www.dianping.com/shop/G7sHtVJBI8fWn45Q/review_all'
headers = {
    'Accept': 'text/,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
    'Accept-Encoding': 'gzip, deflate',
    'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
    'Cache-Control': 'max-age=0',
    'Connection': 'keep-alive',
    'Cookie': 填入自己的cookies,
    'Host': 'www.dianping.com',
    'Referer': 'http://www.dianping.com/shop/G7sHtVJBI8fWn45Q',
    'Upgrade-Insecure-Requests': '1',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36',
}
response=requests.get(url=url,headers=headers)
response.encoding='utf-8' #編碼用utf-8
#這裡我把html下載下來,為了後面好分析,如果一直請求會被封
with open('Ajian.html','w',encoding='utf-8') as f:
    f.write(response.text)
content=response.content
html=etree.HTML(content)
css_url='http:'+html.xpath('/html/head/link[4]/@href')[0]
print(css_url)

下面我們透過css_url獲取cvg的url:

#這裡請求頭可以用pyhon的,當然看個人習慣
headers1={
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36'
}
css_response=requests.get(url=css_url,headers=headers1)
response.encoding='utf-8'
# print(css_response.text)
#這裡我對 css網頁也進行了儲存
with open(r'Ajian.css','w',encoding='utf-8') as f:
    f.write(css_response.text)
#這裡xpath無法用,我們可以用正則
svg_group=re.search(r'svgmtsi\[class\^="(\w+)"].*?background-image: url\((.*?)\);', css_response.text)
#key_letter是為了獲取屬性class的值,在後面我們會用到它,用完你會發現評論中屬性class的值都是iz開頭,這裡會根據點評svg的變化自動變化。
key_letter=svg_group.group[1]
svg_url='http:'+svg_group[2]
print(key_letter)
print(svg_url)

獲取svg:

svg_response=requests.get(url=svg_url,headers=headers1)
with open('Ajian.svg','w',encoding='utf-8') as f:
    f.write(svg_response.text)
# print(svg_response.text)

接下來我們開始進行獲取評論,把對映關係用字典表示出來:
(說實話這裡搞得有點麻煩不過,可以再最佳化的)
首先把y與svg每行的漢字用字典建立關係,也就是字典dic。
然後再透過x吧評論中屬性class的值與對應的漢字建立字典關係。

with open('Ajian.svg','r',encoding='utf-8') as f:
    svg_html=f.read()
list1=re.findall(r'id="(\d+)" d="M0 (\d+) ',svg_html)
# print(list1)
href_list=['#'+i[0] for i in list1]
y_list=[]
for i in list1:
    y_list.append(str(int(i[1])-23))
# print(y_list)
# print(href_list)
# print(len(y_list),len(href_list))
dic1={}
key_letter='iz'
with open('Ajian.css','r',encoding='utf-8') as f:
    css_html=f.read()
for i in dic.keys():
    tuple_list=re.findall('\.('+key_letter+'\w+)\{background:-(\d+)\.0px -'+i+'\.0px;\}',css_html)
    # print(tuple_list)
    for m in tuple_list:
        x=int(int(m[1])/14)
        dic1[m[0]]=dic[i][x]
# print(dic1)

接下來我們要回到圖一原始碼中先用正則把評論的程式碼取到,然後進行替換:

with open('Ajian.html','r',encoding='utf-8') as f:
    html=f.read()
comment_list=re.findall('<div class="review-words Hide">\s+(.*?)\s+<div class="less-words">',html)
# print(comment_list)
for i in comment_list:
    key_list=re.findall('<svgmtsi class="(\w+)"></svgmtsi>',i)
    # print(i)
    # print(key_list,'\n\n')
    for n in key_list:
        # print(dic1[n])
        #這裡是透過迴圈把刑如<svgmtsi class="izu41"></svgmtsi>的替換相應的漢字
        i=i.replace('<svgmtsi class="{}"></svgmtsi>'.format(n),dic1[n])
        #這裡這裡img_list是為了把那些評論的表情包刪掉。
        img_list=re.findall(r'<img.*?;',i)
        for img in img_list:
            i=i.replace(img,'')
    print(i)

4結果展示:
在這裡插入圖片描述
可以看到還是有一些雜質,但是還是與評論對比,還是可以的

總結

這個感覺挺難的,但是不要怕,還是可以搞出來的。要相信自己哦,大眾點評變化很快,可能今天還能爬,明天就不能用了,所以我的這種只能解決裡面的思路。
我這裡有許多可以改進的地方,望大家指出。
本人搞爬蟲僅僅是為了興趣,

參考連結https://cloud.tencent.com/developer/article/1698225
https://zhuanlan.zhihu.com/p/111126062
https://blog.csdn.net/qq_41562377/article/details/105539643?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522160474038419724839212978%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=160474038419724839212978&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_v2~rank_v28-9-105539643.pc_search_result_cache&utm_term=%E5%A4%A7%E4%BC%97%E7%82%B9%E8%AF%84%E7%88%AC%E8%99%AB&spm=1018.2118.3001.4449

本文章已修改原文用詞符合繁體字使用者習慣使其容易閱讀

版權宣告:此處為CSDN博主「Ajian呀」的原創文章,依據CC 4.0 BY-SA版權協議,轉載請附上原文出處連結及本宣告。

原文連結:https://blog.csdn.net/weixin_45886778/article/details/109549657