in my 雑記

プログラミング bump 日々のことなど

利用可能なproxyを探して匿名でスクレイピングする[python]

f:id:inmyzakki:20170902164248p:plain

はじめに

久々のpython記事です。
最近はNodeJsで遊んでいたんですけど、
やっぱりpythonは書きやすくていいですね。

出来ること

・無料で公開されているproxyをスクレイピングする。
・取得したproxyが使えるものかチェックする。
・使えなかったらほかのpeoxyを使う。
・取得したproxyを使ってrequestでスクレイピングができる。
・取得したproxyを使ってseleniumでwebブラウザの自動操作ができる。
・ループ処理でインターバル時間ごとにスクレイピングする。
・スクレイピングするごとにproxyを新しいものにする。

プログラム

chromeが正式にヘッダーレスに対応したので、
ヘッダーレスオプションを付けてヘッダーレスにしてます。喜び。
しかし、プロキシの設定と同時にできないみたいです。悲しみ。

スクレイピングはjavascriptがあるならrequests、ないならseleniumといった
使い分けがベストです。
当然requestsの方が早いです。
なので出来るだけ、requestsを使いましょう。
どうしようもない時のみ、seleniumを使うのがいいです。
chromedriverはここから最新のものを落としてください。

ブラウザの自動操作がしたいならselenium一択です。

以下ソース。


################インポート################
import requests
from bs4 import BeautifulSoup
from selenium import webdriver
from time import sleep
from selenium.webdriver.chrome.options import Options
import random
import re
################インポート################



################可変値################
# ターゲットURL
targetUrl = 'https://www.yahoo.co.jp'
# この時間(秒)でターゲットURLにアクセスできないプロキシは使わない
PermissionTime = 5
# スクレイピングするインターバルタイム(秒)
# intervalTime = random.randint(900,10800) 15分~3時間のランダム
intervalTime = 600
# chromedriverパス
chromePath = r"XXXXXXXXXXXX"
################可変値################



################固定値################
# プロキシサイトのURL
proxyUrl = 'http://www.cybersyndrome.net/plr6.html'
################固定値################



################関数群################
# プロキシのリストをスクレイピングする関数
def getProxy():
    # seleniumの設定、ヘッダーレスモードとクロームのパスを指定
    options = Options()
    options.add_argument('--headless')
    driver = webdriver.Chrome(chromePath,chrome_options=options)
    # サイトへアクセス
    driver.get(proxyUrl)

    # BeautifulSoupさんにhtmlのソースを見やすくしてもらう
    soup = BeautifulSoup(driver.page_source.encode('utf-8'), 'html.parser')
    data = soup.find_all('td', id=re.compile("^n")) #正規表現でIDを取得

    # クローム閉じる
    driver.close()

    # プロキシを整形して配列に入れる
    proxyList = []
    for proxyT in data:
        proxyList.append('http://'+proxyT.text)
    return proxyList

# プロキシの選定関数
def is_bad_proxy(pip):
    try:
        # seleniumの設定、プロキシを通してクロームのパスを指定
        options = Options()
        options.add_argument("--proxy-server=" + pip)
        # options.add_argument('--headless') stackflow曰くヘッダーレスとプロキシは同時で使用できないらしい
        driver = webdriver.Chrome(chromePath,chrome_options=options)
        # webサイトへのタイムアウト時間を設定。もしこの時間内にアクセスできないならexceptに入る
        driver.set_page_load_timeout(PermissionTime)
        # アクセスして閉じる
        driver.get(targetUrl)
        driver.close()
    except:
        driver.close()
        print("タイムアウト")
        return True
    return False

# プロキシのリストをまわして、いいプロキシを見つける。見つからなかったらNoneを返す
def checkProxy(proxys):
    temp = None
    for item in proxys:
        if is_bad_proxy(item):
            print("Bad Proxy:", item)
        else:
            print("Nice Proxy:", item)
            temp = item
            break
    else:
        return None
    return temp
################関数群################



################メイン################
# 無限ループ
while(True):
    # プロキシを取得していいプロキシを見つける
    proxys = getProxy()
    good_proxy = checkProxy(proxys)

    # いいプロキシがあったら処理する
    if good_proxy is not None:

        ################スクレイピングする処理(javascriptない場合)################
        proxies = {'http': good_proxy}
        html = requests.get(targetUrl, proxies=proxies)
        soup = BeautifulSoup(html.content, 'html.parser')
        # ちゃんとスクレイピング出来てるか表示
        print(soup)
        ################スクレイピングする処理(javascriptない場合)################



        ################スクレイピングする処理(javascriptある場合################
        options = Options()
        options.add_argument("--proxy-server=" + good_proxy)
        # options.add_argument('--headless') stackflow曰くヘッダーレスとプロキシは同時で使用できないらしい
        driver = webdriver.Chrome(chromePath,chrome_options=options)
        driver.get(targetUrl)
        soup = BeautifulSoup(driver.page_source.encode('utf-8'), 'html.parser')
        driver.close()
        # ちゃんとスクレイピング出来てるか表示
        print(soup)
        ################スクレイピングする処理(javascriptある場合)################

    else:
        print("条件にマッチするプロキシがありません。")
    sleep(intervalTime)
################メイン################

おわり

同一IPでの操作するとフリな条件になるサイトがあったので、それ用に作りました。
有料でもいいから、そこそこスピードが出て、
好きな時にIPを変えられるプロキシサーバーってないのかなぁ。