1. 程式人生 > >DC學院資料分析師(入門)學習筆記----高階爬蟲技巧

DC學院資料分析師(入門)學習筆記----高階爬蟲技巧

    對於網站來說,實際上是不願意讓大家去爬取它的內容的,因為爬蟲可能會對真實的使用者帶來不太好的影響(很多網站會限制流量,尤其是對爬蟲產生的流量,會對伺服器帶來一定的壓力)。所以網站會對爬蟲有一定的抵制,如果不注意爬蟲的技巧,有可能就被網站封殺IP,以致暫停了。

    那麼如何能夠輕鬆繞過部分的反爬蟲限制,書寫我們的爬蟲呢??

1.設定程式休止時間

    連續不斷的進行爬蟲的抓取,就會被網站監測出來是一個爬蟲程式。所以,我們應該在能夠接受的速度內,儘量降低一下自己爬取的頻率(中間停1-5秒,再去爬下一個),以免對這些網站產生不必要的影響,這樣做也對網站的負荷會比較好。

    n

為你想要實現的時間間隔

import time
time.sleep(n)

2.設定代理

    設定代理的原因主要有兩個:

    ①、有時候需要爬取的網站,通過我們的網路IP沒有辦法去進行訪問。所以需要設定代理。如:在教育網裡訪問外網的網站;國內的IP有時候無法訪問國外的網站等。

    ②、有時候,不管我們怎麼設定我們的爬取頻率,在爬取如新浪微博、Facebook等這些很成熟的網站的時候,這些網站的反爬蟲技術很高超,所以會很快的檢測到我們的機器爬蟲程式,從而會把我們登入訪問的ip地址封掉。比如針對facebook,它會禁止這個ip地址再去訪問它的網站,即使我們重新啟動爬蟲,從無論是正常從瀏覽器訪問還是爬蟲訪問,Facebook
都一律不允許這個ip地址再去訪問它的網站。

    那麼,通過代理伺服器如何進行呢??

    傳統:通常直接使用我們的電腦去訪問網頁。

    通過代理伺服器:我們傳送一個網路的請求,會首先發送到代理伺服器上,代理伺服器再把這個請求轉發到網頁所在的網站伺服器。網站伺服器回覆的反饋會先發送到代理伺服器上,代理伺服器再發送給我們的電腦。在這種情況下,只要我們的電腦和代理伺服器的連線是合理快速的,代理伺服器和網站伺服器的連線是順暢快速的,通過代理伺服器往往就可以加速我們訪問目標網頁的速度,甚至我們可以訪問到一些我們之前無法訪問的網頁內容。

    那麼,如何通過python訪問代理伺服器呢??

#使用urllib.request的兩個方法進行代理的設定
proxy = urlrequest.ProxyHandler({'https': '47.91.78.201:3128'})
opener = urlrequest.build_opener(proxy)


    代理伺服器的存在,可以應對網站禁止某個IP訪問的反爬蟲措施,代理伺服器有著不同的匿名型別,通常我們會挑選中、高級別的代理伺服器來訪問網頁。(使用低級別的是沒有用的,網站還是能夠知道我們的真實IP,對於我們的爬取時沒有任何幫助的,因為它還是能夠封掉我們的真實IP


    3.設定User-Agent

    網站是可以識別我們是否在使用Python進行爬取,需要我們在傳送網路請求時,把header部分偽裝成瀏覽器。

opener.addheaders = [('User-Agent','...')]

           用不同瀏覽器訪問的header字串,放入上述程式碼省略號的部分即可。

    常用的瀏覽器header有:


      網上檢視還有這些:

    1.QQ瀏覽器: Mozilla/5.0 (compatible; MSIE 10.0; WindowsNT6.1; WOW64; Trident/6.0; QQBrowser/7.7.24962.400)(我在程式碼中用的是這個)

    2. IE瀏覽器:Mozilla/5.0(compatible; MSIE 10.0;Windows NT 6.1; WOW64; Trident/6.0)

示例:Place PulseGoogle街景圖爬取

    這是MIT的學術專案,爬取不同城市的街景地圖,然後讓人去手工標註圖片中的城市哪個更安全,更有趣等等。

舉個例子,下面這兩個城市的圖景。如果認為左邊更好的話,就點選左邊的城市,如果認為差不多的話就點選等號,

如果認為右邊更好的話,就點選右邊的城市。

    MIT會統計這些標註結果。

    這個資料集是這樣的:(左邊城市是什麼,右邊城市是什麼,某人的打分)


    下載下來:

 

    結構:


    逗號來分隔每一個屬性裡面的值

           核心任務:

   把對應每一個圖片ID的谷歌街景圖片,根據它告訴我們的這個圖片所在的GPS的經緯度的位置,利用readme中看到的google mapapi,把這個圖片下載下來。

    程式碼及註釋:

# coding=utf-8

import urllib.request as urlrequest
import time
import random

# 1.準備工作:載入包,定義儲存目錄,連線API
IMG_PATH = './imgs/{}.jpg'  # 最終會把下載的圖片存到這個目錄下面
DATA_FILE = './data/votes.csv'

# 記錄一下已經下載了哪些圖片,把圖片id放在裡面,這樣如果下載中止也能知道哪些已經下載了,
# 這樣在下載一個圖片之前,我們可以先判斷一下這個圖片的id是否在這個檔案中有,如果有,就不用再下載了。
STORED_IMG_ID_FILE = './data/cached_img.txt'

STORED_IMG_IDS = set()  # 把已經下載的圖片的id放在一個集合裡面

# readme中提到的google針對下載街景地圖的api
# 我們需要修改的是location,即經緯度
IMG_URL = 'https://maps.googleapis.com/maps/api/streetview?size=400x300&location={},{}'

# 2.應用爬蟲技巧:使用代理伺服器、User-Agent
# 根據網上找到的代理伺服器來更新一下,因為代理伺服器可以執行的時間也是有限制的
proxy = urlrequest.ProxyHandler({'https': '173.213.108.111:3128'})  # 設定代理伺服器的地址
#opener = urlrequest.build_opener(proxy)
opener = urlrequest.build_opener()

# 設定User-Agent
opener.addheaders = [('User-Agent',
                      'Mozilla/5.0 (compatible; MSIE 10.0; WindowsNT 6.1; WOW64; Trident/6.0; QQBrowser/7.7.24962.400) ')]

urlrequest.install_opener(opener)

# 3.讀取圖片的id
with open(STORED_IMG_ID_FILE) as input_file:
    for line in input_file:
        STORED_IMG_IDS.add(line.strip())

# 4.根據提供的votes.csv,進行google街景圖片的爬取
with open(DATA_FILE) as input_file:  # 讀取votes.csv
    skip_first_line = True
    for line in input_file:
        if skip_first_line:  # 因為第一行是屬性行,所以跳過
            skip_first_line = False
            continue
        # 根據逗號就行拆分成各個屬性(這些屬性在readme中可以看到)
        left_id, right_id, winner, left_lat, left_long, right_lat, right_long, category = line.split(',')

        # 針對左邊的圖片
        if left_id not in STORED_IMG_IDS:  # 如果左邊的圖片還沒有下載
            print('saving img {}...'.format(left_id))
            urlrequest.urlretrieve(IMG_URL.format(left_lat, left_long), IMG_PATH.format(left_id))  # 檔案命名為這個圖片的id
            STORED_IMG_IDS.add(left_id)  # 把已經下載的圖片的id加進集合中
            with open(STORED_IMG_ID_FILE, 'a') as output_file:  # 把已經下載的圖片的id新新增進cached_img.txt中
                output_file.write('{}\n'.format(left_id))
            time_interval = random.uniform(1, 5)
            time.sleep(time_interval)  # wait some time, trying to avoid google forbidden (of crawler)

        # 針對右邊的圖片
        if right_id not in STORED_IMG_IDS:
            print('saving img {}...'.format(right_id))
            urlrequest.urlretrieve(IMG_URL.format(right_lat, right_long), IMG_PATH.format(right_id))
            STORED_IMG_IDS.add(right_id)
            with open(STORED_IMG_ID_FILE, 'a') as output_file:
                output_file.write('{}\n'.format(right_id))
            time_interval = random.uniform(1, 5)
            time.sleep(time_interval)  # wait some time, trying to avoid google forbidden (of crawler)

        國外伺服器的代理地址,可以在 http://www.kuaidaili.com/free/outha/這個網站中找到。


          可以看到每個地址對應ip地址所在的國家,匿名的程度等等。

    這裡需要注意我們不能使用低階(Transparent)代理。

          先來執行不使用代理伺服器的程式:


     速度很慢,儲存不動,google在大陸訪問起來還是比較困難的。


 

    執行設定代理伺服器的程式:



       可以順利進行,這說明我們成功連線到了代理的一個伺服器上,再通過這個代理伺服器連線到了google上。

 

       在資料夾裡可以檢視到我們從googlemap中下載到的圖片以及圖片的id