【Python3爬蟲】大眾點評爬蟲(破解CSS反爬)


本次爬蟲的爬取目標是大眾點評上的一些店鋪的店鋪名稱、推薦菜和評分信息。

 

一、頁面分析

進入大眾點評,然后選擇美食(http://www.dianping.com/wuhan/ch10),可以看到一頁有15家店鋪,而除了店鋪的名稱,還能看到店鋪的地址、推薦菜、評分等信息,看起來都沒什么問題。

打開開發者工具,然后選擇查看一下評分,就發現事情沒那么簡單了(如下圖)。這些評分的數字去哪兒了呢?

其實這些數字是SVG矢量圖,SVG矢量圖是基於可擴展標記語言,用於描述二維矢量圖形的一種圖形格式,通過使用不同的偏移量就能顯示不同的字符,這樣就能很巧妙地隱藏信息了,如果我們用xpath去解析網頁得到的就是一個個""。這次爬蟲的難點就在於如何得到這些評分的信息,既然我們能夠知道它是怎么反爬的,那我們是不是就能想辦法實現反反爬呢?先說下破解思路吧:首先要解析網頁,找到這個網頁使用的SVG矢量圖,拿到這個矢量圖后,如果我們能得到每個數字對應的偏移量,那就能將這些偏移量轉化成圖片中的數字了。

 

 二、破解步驟

首先查看網頁源碼,既然使用的是SVG矢量圖,那我們搜索一下svg會不會有驚喜呢?果然有驚喜:

把這個鏈接復制一下,然后打開這個鏈接,會看到有很多的class名稱和background,這么多的數據,怎么知道有沒有我們想要的東西呢?這時候搜索一下unbq2:

可以看到unbq2這個class對應的background為(-199.0px,-109.0px),但是我們還是沒有辦法得到具體的數字啊,怎么辦呢?

我們再搜索一下svg會有什么結果呢?這一步會得到幾個以.svg結尾的鏈接,將這些鏈接提取出來:

span[class^="ma"]{background-image: url(//s3plus.meituan.net/v1/mss_0a06a471f9514fc79c981b5466f56b91/svgtextcss/9e045e6574fb7ae10b5aae4ae4a0c444.svg);
span[class^="yj"]{background-image: url(//s3plus.meituan.net/v1/mss_0a06a471f9514fc79c981b5466f56b91/svgtextcss/39510b070120e6a5b7c8754ab729ee2e.svg);
span[class^="dz"]{background-image: url(//s3plus.meituan.net/v1/mss_0a06a471f9514fc79c981b5466f56b91/svgtextcss/8eecf780b3c9ecefd5ad508502dd80a5.svg);
span[class^="un"]{background-image: url(//s3plus.meituan.net/v1/mss_0a06a471f9514fc79c981b5466f56b91/svgtextcss/39ecd4a57969825db02c38a01f4f34c6.svg);

可以看到以"un"開頭的class使用的背景圖片的鏈接就是//s3plus.meituan.net/v1/mss_0a06a471f9514fc79c981b5466f56b91/svgtextcss/39ecd4a57969825db02c38a01f4f34c6.svg

這就是我們要找的SVG矢量圖了,現在的問題就在於如何將偏移量轉化成對應的數字呢?首先把這些數字提取出來:

99851465728255648017534661485297040380627087820023

03763928255311814779807306445209731282368541175419

06266544999197136339

然后打開開發者工具,可以發現每個數字都有對應着一組x和y的值:

 

在前面的分析中我們知道數字6對應的偏移量是(-199.0px,-109.0px),然后我們也可以分析一下別的數字對應的偏移量,然后通過這些分析可以知道y方向上的偏移量只是為了確定這個class對應的數字在哪一行,而x方向的偏移量需要進行一下處理,具體方法為:

(x方向上的偏移量+7)/(-12)

 比如(-199+7)/(-12)=16,這個16就表示對應的數字索引為16(第一個數字索引為0),然后y方向的偏移量對應的行數為3,最后從上面的數字中尋找第3行第17個數字--正好為6,也就是說unbq2這個class對應的數字就是6,這樣我們就已經成功實現了反反爬。

 

三、爬取步驟

由於大眾點評會對我們的UserAgent和Cookie進行檢查,所以在爬取的時候要帶上Cookie,而且如果一直用一個UserAgent也會被識別出來,所以得采用不同的UserAgent。這里我要分析一個第三方模塊:fake_useragent,沒有安裝這個模塊的可以使用pip命令進行安裝。我們通過使用這個模塊就能得到隨機的UserAgent了,使用方法如下:

1 from fake_useragent import UserAgent 2 
3 ua = UserAgent() 4 for i in range(3): 5     print(ua.random)

運行結果如下:

店鋪名稱和推薦菜的爬取相對簡單,這里就不贅述了,主要說一下如何爬取店鋪的評分信息。

在我們得到網頁的源碼之后,需要先把css文件的url提取出來:

# 提取css文件的url
css_url = "http:" + re.search('(//.+svgtextcss.+\.css)', html).group()

然后將以"un"開頭的class名稱和對應的偏移量全部提取出來,以供后面使用:

css_res = requests.get(css_url)
# 這一步得到的列表內容為css中class的名字及其對應的偏移量
css_list = re.findall('(un\w+){background:(.+)px (.+)px;', '\n'.join(css_res.text.split('}')))

這里還要對得到的數據進行一下處理,因為y方向上的偏移量並不參與計算,最終得到的y_dict中的鍵是y方向上的偏移量,值是y方向上的偏移量對應的行數:

# 過濾掉匹配錯誤的內容,並對y方向上的偏移量初步處理
css_list = [[i[0], i[1], abs(float(i[2]))] for i in css_list if len(i[0]) == 5]
# y_list表示在y方向上的偏移量,完成排序和去重
y_list = [i[2] for i in css_list]
y_list = sorted(list(set(y_list)))
# 生成一個字典
y_dict = {y_list[i]: i for i in range(len(y_list))}

然后我們要提取以”un“開頭的class所對應svg圖片的url,並訪問這個url,將圖片中的數字都提取出來:

# 提取svg圖片的url
svg_url = "http:" + re.findall('class\^="un".+(//.+svgtextcss.+\.svg)', '\n'.join(css_res.text.split('}')))[0]
svg_res = requests.get(svg_url)
# 得到svg圖片中的所有數字
digits_list = re.findall('>(\d+)<', svg_res.text)

進行到這一步,我們就已經得到了所有以un開頭的class對應的偏移量和所有的數字了,然后我們就可以利用前面的計算方法將這些偏移量轉變成對應的數字了,也就能得到每個店鋪的評分信息了。

 最終運行結果如下:

 

完整代碼已上傳到GitHub


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM