記一次基於Cloudflare服務的爬蟲

前言

前幾天有個朋友託我幫忙爬一個網站,第一次打開那個網站時,我去,它居然就要驗證碼,不過當時是想加幾個header應該就能解決,不過事實證實我仍是錯了。接下來將記錄下爬蟲中遇到的一些坑以及解決辦法。javascript

開始

相關

目標網站:AVADA – Avada Commerce
使用了Cloudflare的cdn服務,並且Cloudflare又和百度有合做,因此咱們的訪問異常時,就會被百度的雲加速服務給攔截下來。css

亂碼問題

原本是準備用比較拿手的java寫這次爬蟲,java請求返回的內容老是出現一些亂碼的問題。已經設置爲utf-8方式而且像gzip、br等解壓縮都嘗試了,稍微好點的狀況只有body標籤內的內容爲亂碼,糟糕的狀況就是整個返回的內容皆爲亂碼。後來就用python試了試,亂碼問題直接沒了,有點迷!html

驗證碼問題

以前用python解決亂碼問題後,緊接着又出現的就是訪問須要驗證碼了。當時我是瀏覽器裏訪問不須要驗證碼,但python訪問無論如何,一直出現百度雲加速的驗證碼認證。出現這種狀況,個人第一反應是python中是否是少了某些關鍵頭部,因而將瀏覽器中的header帶到python中一 一去試,但並無起到啥做用。這裏我就賊納悶了,究竟爲甚嗎???後來才忽然想起來我瀏覽器走了代理,因而我乾脆給電腦設置了個全局代理,而後用python繼續訪問,讓人感動的一幕發生了-----> 命令行中返回了目標網站的頁面源代碼!這時我才察覺,個人本地IP已經進入了目標網站的黑名單 。到這裏,驗證碼也就繞過了。java

JS致使頁面url發生重定向

在把前面的目標網站的頁面下載到本地後,而後用瀏覽器打開該文件,瀏覽器會加載頁面中的一些圖片css還有js等資源文件,其中有個js會檢測當前頁面url中的協議是不是https,若是不是,將重定向至對應的https協議的頁面。這裏顯然,咱們打開的本地文件url是文件的目錄,不是以https開始的。
好比火狐瀏覽器中打開目標文件,地址欄的url以下python

file:///C:/Users/Asche/vscode/Shopify/temp/Customers/How%20to%20add%20or%20edit%20a%20customer%E2%80%99s%20address.html

被重定向後的url以下瀏覽器

https://c/Users/Asche/vscode/Shopify/temp/Customers/How%20to%20add%20or%20edit%20a%20customer%E2%80%99s%20address.html

顯然,重定向後的頁面是不存在的。固然,咱們也能夠在頁面重定向前手動取消重定向的請求,不過這樣畢竟體驗很差,因此繼續想辦法解決重定向問題。
因而,準備尋找起重定向做用的·js代碼,瀏覽一番渲染後的頁面源代碼,發如今body標籤結束前,多了這樣一段代碼:安全

<script type="text/javascript" id="">"https:"!=location.protocol&&(location.href="https:"+window.location.href.substring(window.location.protocol.length));</script>

並且這段代碼在最初的頁面內是沒有的,說明是被別的js動態加載進來的。因此我就選擇其中的一段代碼‘location.protocol‘,在其他幾個可疑的js文件內搜索,遺憾的是沒有找到。
另外原本想使用js的debug功能,奈何一到dubug頁面,瀏覽器就未響應!!!
最後沒有辦法,我就直接在目標文件上選擇性的註釋js引入,可疑的js文件都被註釋掉了,卻發現任然存在重定向!!!最後,只剩下一個google相關的js,把那個js註釋掉,重定向終於消失了!那段js代碼大概以下:async

<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-NPVH4QZ');</script>

原本覺得這段代碼就像google分析那樣的一些沒啥影響的Google服務,結果卻讓人有點意外!多是出於安全的考慮把。
到這裏,重定向也解決!網站

主要部分Python代碼

import requests
import os
from bs4 import BeautifulSoup

# Author: Asche
# date: 2019年7月6日
print('Shopify start...')

BASE_URL = 'https://avada.io'
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36',
           'Cookie': '__cfduid=db73a1a3b63a54e86f435f615f5ec37791562300679; _ga=GA1.2.1048718546.1562300686; _gid=GA1.2.312498482.1562300686',
           'Accept': '*/*', 'Accept-Encoding': 'gzip', 'Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7,mt;q=0.6'}


def getHtml(url):
    req = requests.get(url, headers=headers)
    return req.text


def saveFile(name, dir, content):
    folder = os.path.exists(dir)
    if not folder:
        os.mkdir(dir)
    with open( dir + '/' + name.replace('/', '_') + '.html', 'w', encoding='utf-8') as f:
        f.write(content)


def crawlSubpage(url, dir):
        subPage = requests.get(url, headers=headers)
        # print(strHome.headers)

        soup = BeautifulSoup(subPage.content, 'lxml')
        print(soup.title)

        titles = soup.select('div.collection a')
        for title in titles:
            print(title.text, title['href'])
            saveFile(title.text, dir, getHtml(title['href']))


strHome = requests.get(BASE_URL, headers=headers)
# print(strHome.text)
print(strHome.headers)


soup = BeautifulSoup(strHome.content, 'lxml')
# print(soup.prettify)
print(soup.title)

titles = soup.select('h3.header a')
for title in titles:
    print(title.text, title['href'])
    crawlSubpage(title['href'], title.text)
相關文章
相關標籤/搜索