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

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

 

1、頁面分析

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

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

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

 

 2、破解步驟

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

把這個連接複製一下,而後打開這個連接,會看到有不少的class名稱和background,這麼多的數據,怎麼知道有沒有咱們想要的東西呢?這時候搜索一下unbq2:ide

能夠看到unbq2這個class對應的background爲(-199.0px,-109.0px),可是咱們仍是沒有辦法獲得具體的數字啊,怎麼辦呢?svg

咱們再搜索一下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.svgurl

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

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,這樣咱們就已經成功實現了反反爬。

 

3、爬取步驟

因爲大衆點評會對咱們的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

相關文章
相關標籤/搜索