pyhton2爬虫 爬IP IP代理池 urllib2设置 scrapy设置

目录

前言

获取IP

其他代理网站

IP验证

 urllib2配置IP

Scrapy配置IP

常规方法:

我的写法:


前言

使用代理IP,这是爬虫/反爬虫的利器,通常也是最好用的。

很多网站会检测某一段时间某个IP的访问次数(通过流量统计,系统日志等),如果访问次数多的不像正常人,它会禁止这个IP的访问。

扫描二维码关注公众号,回复: 3414579 查看本文章

所以我们可以设置一些代理服务器,每隔一段时间换一个代理,就算IP被禁止,依然可以换个IP继续爬取。

获取IP

本次主要爬取普通IP,感谢西刺网

下面是完整获取代码,请求头如果想用自己的,就找到网页体文件,更换对应header即可

项目文件

 西刺并没有反爬虫,只要不大量索取就不会被Ban,这里我们也只抓了3页的IP,后面对抓到的IP进行了筛选,去掉了存活时间小于

1天和延迟过高的IP.

# -*- coding:UTF-8 -*-
import requests
from bs4 import BeautifulSoup
from lxml import etree
import re
import string
import json

#从西刺网爬取id
def ipCrawl(page):
    #requests的Session可以自动保持cookie,不需要自己维护cookie内容
    filename = 'D:\python\IpAgentPool\\name\\name\ip.json'  # 储存位置
    count = 0

    for i in range(1,page+1):

        reqSession = requests.Session()
        url = 'http://www.xicidaili.com/nt/%d' % i  # 普通ip
        headers = {'Upgrade-Insecure-Requests': '1',
                   'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36',
                   'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
                   'Referer': 'http://www.xicidaili.com/nn/',
                   'Accept-Encoding': 'gzip, deflate, sdch',
                   'Accept-Language': 'zh-CN,zh;q=0.8',
                   }
        response_text = reqSession.get(url = url, headers = headers)
        response_text.encoding = 'utf-8'
        rephtml = response_text.text
        mainForm = BeautifulSoup(rephtml, 'lxml')
        tableForm = BeautifulSoup(str(mainForm.find_all(id='ip_list')), 'lxml')
        List_ip = tableForm.table.contents

        pattern1 = re.compile(r'\d.\d')
        pattern2 = re.compile(r'u.*')
        pattern3 = re.compile(r'\d+')
        _json = dict()


        for index in range(len(List_ip)):
            if index % 2 == 1 and index != 1:
                dom = etree.HTML(str(List_ip[index]))
                LiveTime = dom.xpath('//td[9]')[0].text
                LiveTime1 = pattern2.search(LiveTime).group()
                ConSpeed = dom.xpath('//td[7]/div/@title')[0]
                ConSpeed1 = pattern1.search(ConSpeed).group()
                if LiveTime1 == "u5929" :
                    if string.atof(ConSpeed1) <0.3:  #取掉生存天数过小和响应时间过长的ip
                        count = count+1
                        _json["ip"] = dom.xpath('//td[2]')[0].text
                        _json["port"] = dom.xpath('//td[3]')[0].text
                        _json["protocol"] = dom.xpath('//td[6]')[0].text
                        _json["LiveTime"] = pattern3.search(LiveTime).group()+'天'
                        _json["ConSpeed"] = ConSpeed1+'秒'
                        with open(filename, 'a') as outfile:  # 追加模式
                            json.dump(_json, outfile, ensure_ascii=False)
                        with open(filename, 'a') as outfile:
                            outfile.write(',\n')
        print "第%d页爬取完成,该页%d条ip" %(i,count)


if __name__ == '__main__':
    ipCrawl(3)

 红框的[]是手动加的,主要是为了读取方便。

 其他代理网站

快代理免费代理

Proxy360代理

全网代理IP

IP验证

在网上搜集了几种方法。

1.放到专门网站查询。

2.使用该IP访问制定网站,如果返回状态为200,表示这个代理是可以使用的。详见https://www.jianshu.com/p/588241a313e7

3.网友提供,查看IP是否可以PING通,还可以看丢包率。觉的还不错,就写了下来。

# -*- coding:UTF-8 -*-
import subprocess as sp
from lxml import etree
import requests
import random
import re
import random
import json

class IpFilter():
    def __init__(self):
        self.ip = ''

    def check_ip(self):
        cmd = "ping -n 3 -w 3 %s" # 命令 -n 要发送的回显请求数 -w 等待每次回复的超时时间(毫秒)
        p = sp.Popen(cmd %self.ip, stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.PIPE, shell=True)  # 执行命令
        lose_time = re.compile(u"丢失 = (\d+)", re.IGNORECASE)
        out = p.stdout.read().decode("gbk") # 获得返回结果并解码
        print (out)
        lose_time = lose_time.findall(out) # 丢包数
        # 当匹配到丢失包信息失败,默认为三次请求全部丢包,丢包数lose赋值为3
        if len(lose_time) == 0:
            print "----------------LOST IP PACKET---------------------"
            return False
        else:
            lose = int(lose_time[0])
            if lose > 1:
                return False
            else:
                return True

    def getAndUpdateIp(self):
        file1 = open('D:\python\IpAgentPool\\name\\name\ip.json', 'r')  # 打开文件
        jsonDict = json.load(file1)  # 加载json
        file1.close()  # 关闭连接
        index = random.randint(0, len(jsonDict))  # 随机下角标
        ipRandom = jsonDict[index]["ip"]  # 随机IP
        print '----random IP IS----------:%s' % str(ipRandom)
        # 测试ip
        self.ip = ipRandom
        if self.check_ip():
            print '-----------------Good IP--------------'
            return jsonDict[index]["protocol"]+'://'+jsonDict[index]["ip"]+':'+jsonDict[index]["port"]
        else:
            print '-----------------Bad IP----------------'
            return False



if __name__ == '__main__':
    ipf = ipFilter()
    print ipf.getAndUpdateIp()

 urllib2配置IP

当代理IP足够多,就可以像随机获取User-Agent一样,随机选择一个代理去访问网站。

import urllib2
import random

proxy_list = [
    {"http" : "124.88.67.81:80"},
    {"http" : "124.88.67.81:80"},
    {"http" : "124.88.67.81:80"},
    {"http" : "124.88.67.81:80"},
    {"http" : "124.88.67.81:80"}
]
# 随机选择一个代理
proxy = random.choice(proxy_list)# 使用选择的代理构建代理处理器对象
httpproxy_handler = urllib2.ProxyHandler(proxy)

opener = urllib2.build_opener(httpproxy_handler)

request = urllib2.Request("http://www.baidu.com/")
response = opener.open(request)print response.read()

Scrapy配置IP

常规方法:

settings.py 将大量IP添加到配置文件集合中。

IPPOOL=[
	
	{"ipaddr":"218.82.33.225:53853"},
        {"ipaddr":"218.82.33.225:53853"},
        {"ipaddr":"218.82.33.225:53853"},
        {"ipaddr":"218.82.33.225:53853"}
]

 这里把默认header和IP都设为None,因为要用自己的。中间那条是自己写的类,文件夹名+middlerwares+类名,后面数字是执行循序,有兴趣的可以去看scrapy中文文档。

DOWNLOADER_MIDDLEWARES = {
#    'myproxies.middlewares.MyCustomDownloaderMiddleware': 543,
     'scrapy.contrib.downloadermiddleware.httpproxy.HttpProxyMiddleware':None,
     'name.middlewares.ProxyMiddleWare':125,
     'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware':None
}

middlewares.py   从配置文件随机读取,请为request对象设置参数

# -*- coding: utf-8 -*-
 
import random
from scrapy import signals
from myproxies.settings import IPPOOL
 
class MyproxiesSpiderMiddleware(object):
 
      def __init__(self,ip=''):
          self.ip=ip
       
      def process_request(self, request, spider):
          thisip=random.choice(IPPOOL)
          print("this is ip:"+thisip["ipaddr"])
          request.meta["proxy"]="http://"+thisip["ipaddr"]

编写spider运行即可。

我的写法:

middlewares.py  从IpFilter获取的IP,如果响应不是200,继续随机获取

# -*- coding: utf-8 -*-
from IpFilter import *
from scrapy import signals
import scrapy
from scrapy import log

class ProxyMiddleWare(object):
    def process_request(self, request, spider):
        ipf = IpFilter().getAndUpdateIp()
        request.meta['proxy'] = ipf

    def process_response(self, request, response, spider):
        '''对返回的response处理'''
        # 如果返回的response状态不是200,重新生成当前request对象
        ipf = IpFilter().getAndUpdateIp()
        if response.status != 200:
            proxy = ipf
            print("this is response ip:" + proxy)
            # 对当前reque加上代理
            request.meta['proxy'] = proxy
            return request
        return response

spider.py

# -*- coding: utf-8 -*-
import scrapy

class mingyanSpider(scrapy.Spider):
    name = "te"
    start_urls = [
        'http://lab.scrapyd.cn/',
    ]

    def parse(self, response):
        for quote in response.css('div.quote'):
            yield {
                '内容': quote.css('span.text::text').extract_first(),
                '作者': quote.xpath('span/small/text()').extract_first(),
            }

        next_page = response.css('li.next a::attr("href")').extract_first()
        if next_page is not None:
            yield scrapy.Request(next_page, self.parse)
            

结果:

有问题留言,我尽力帮助

猜你喜欢

转载自blog.csdn.net/Da___Vinci/article/details/82892437