反爬虫問題への対応(学習中)


1.合理的なHTTPリクエストヘッダの構築
現在、私が一般的に使用しているのはUser-Agentを変更することです.一部のサイトは爬虫類のアクセスが好きではありません.接続オブジェクトを検出します.爬虫類プログラムであればアクセスさせません.
import requests
url='https://www.amazon.cn/'
hd={'User-Agent':'Mozilla/5.0'}
try:
    r=requests.get(url,headers=hd)
    r.raise_for_status()
    print(r.request.headers)
except:
    print('----')


#  
{'User-Agent': 'Mozilla/5.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}

2.注意暗黙入力フィールド
HTMLフォームでは、「抑制」フィールドは、Webソースコードを見ない限り、フィールドの値をブラウザに表示できますが、ユーザーには表示されません.
隠しフィールドでネットワークデータの収集を阻止する方法は主に2つある.1つ目は、フォームページのフィールドがサーバで生成されたランダム変数で表すことです.コミット時にこの値がフォーム処理ページにない場合、サーバは、このコミットが元のフォームページからコミットされるのではなく、ネットワークロボットが直接フォーム処理ページにコミットされると考えている理由があります.この問題を回避する最善の方法は、まずフォームが存在するページで生成されたランダム変数を収集し、フォーム処理ページにコミットすることです.
2つ目の方法は「蜜缶」(honey pot)です.フォームに通常の名前の隠しフィールド(蜜缶の罠を設定する)が含まれている場合、「ユーザー名」(username)や「メールアドレス」などです.(email address)あまりよく設計されていないネットワークロボットは、このフィールドがユーザーに見えるかどうかにかかわらず、このフィールドに直接記入してサーバーに提出することが多く、サーバーの蜜缶の罠にかかります.サーバーはすべての隠しフィールドの真実値を(またはフォームコミットページのデフォルト値とは異なる値)は無視され、暗黙のフィールドに記入したアクセスユーザーもサイトによってブロックされる可能性があります.
どうやって蜜缶の罠を避けるの?
例えば、私たちがネット爬虫類を行うとき、私たちは簡単に情報を収集することができますが、登ったネットフォームのフィールドがCSSを通じて見えないように設定されていると、普通のユーザーはブラウザでは見えないので、このフィールドを記入することはできません.もし果被が記入されたら、爬虫類が乾いている可能性があると思って、あなたを閉鎖します.
この手段は、ウェブサイトのフォームだけでなく、リンク、ピクチャ、ファイル、ロボットによって読み取ることができるが、一般ユーザーがブラウザでは見えないコンテンツにも適用できる.訪問者がウェブサイトの「隠し」コンテンツにアクセスすると、サーバスクリプトがこのユーザーのIPアドレスを封殺し、このユーザーをウェブサイトから蹴り出すか、他の措置を取ってこのユーザーのウェブサイトへのアクセスを禁止するようにトリガーされます.
一例を紹介するhttp://pythonscraping.com/pages/itsatrap.html
from selenium import webdriver
url='http://pythonscraping.com/pages/itsatrap.html'
driver=webdriver.Chrome()
driver.get(url)
items=driver.find_elements_by_tag_name('a')
for item in items:
    if not item.is_displayed():#         
        print('{}     '.format(item.get_attribute('href')))
inputs=driver.find_elements_by_tag_name('input')
for item in inputs:
    if not item.is_displayed():
        print('{}       '.format(item.get_attribute('name')))



#  
http://pythonscraping.com/dontgohere     
phone       
email       

3.独自のエージェントIPプールの作成
サーバは、IPの単位時間当たりの要求回数を検出し、しきい値を超えると、サーバは直接サービスを拒否し、エラー情報を返します.だから、私たちは何らかの方法でIPを偽装することができて、サーバーが私たちの本機から始まった要求を認識できないようにすることができて、このように私たちはIPを閉じることを防止することができます.
ここには1が必要です.ウェブサイトに行って無料のIP 2を取りに行きます.登ったIPが有効かどうかをチェックします.有効なIPを保存する
では、どのようにしてIPが有効かどうかを検出することができますか?第1の方法:requestsを利用する.get(url,timeout=?),timeoutの1つの値を設定して、タイムアウトしたら第2の方式が使えないことを説明します:本機でpingというIPを行って、pingが通じるならば、それではこのIPも他のウェブサイトにアクセスすることができることを説明します
私は2つ目の方法でpythonを利用してSubprocessを実現します.Popen()は、shellパラメータがtrueの場合、shellによってプログラムが実行されるプロセスを作成します.
パラメータ:应对反爬虫问题(正在学习中)_第1张图片
コード:
from bs4 import BeautifulSoup
import requests
import subprocess as sp
import re


def getIP(IPlist):  #         ip,    IPlist
    url = 'http://www.xicidaili.com/nn'  #     IP   
    hd = {'User-Agent': 'Mozilla/5.0'}  #          
    try:
        r = requests.get(url, headers=hd)
        r.raise_for_status()
        r.encoding = r.apparent_encoding
        soup = BeautifulSoup(r.text, 'html.parser')
        #             
        list = (soup.select('tr')[1:])  #  CSS      tr  ,           
        for item in list:  #   
            taglist = item.select('td')  #   td  ,    ,  ,           
            ip = taglist[5].string.lower() + '#' + taglist[1].string + '#' + taglist[2].string  #   #     
            IPlist.append(ip)
    except:
        print('1111')


def check_ip(ip):  #   ip    
    cmd = 'ping -n 3 -w 3 {}'.format(ip)  #     ping     IP,              IP       
    p = sp.Popen(cmd, stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.PIPE, shell=True)  #   Subprocess.Popen        
    out = p.stdout.read().decode('gbk')
    #    
    Lost_Packets = loss(out)
    #     
    time = average_time(out)
    #       ip,     True
    if Lost_Packets <= 1 and time <= 500:  #       1,      500ms
        return True
    else:
        return False


def loss(out):  #       
    match = re.search(r'   = (\d)', out)  #        
    Lost_Packets = int(match.group(1))
    return Lost_Packets


def average_time(out):
    match2 = re.search(r'   = (\d*)ms', out)
    if match2:
        return int(match2.group(1))
    else:
        return 1000


def main():
    IPlist = []
    getIP(IPlist)
    ulist = []  #        IP  
    for IP in IPlist:  #     20 
        elements = IP.split('#')  #  '#'  ,         
        ip = elements[1]
        # print(ip)
        if check_ip(ip):
            ulist.append({elements[0]: elements[1] + ':' + elements[2]})
    print(ulist)
main()


#      
{'http': '111.194.14.157:8118'}, {'https': '106.14.47.5:80'}, {'http': '106.75.225.83:808'}, {'https': '218.59.228.18:61976'}

これでよかった他の更新まで勉強して
参考文献:https://blog.csdn.net/c406495762/article/details/72793480