在日常爬虫工作中,都需要对爬虫程序进行调试,很多时候会遇到关于ip的错误,特别是新入爬虫的朋友,好好的程序突然报错了?要怎么解决,关于ip访问的错误其实很好解决,但是怎么知道解决好了呢?怎么确定是代理ip的问题呢?今天我们就以java爬虫为例来跟大家详细的聊聊。
代理ip的逻辑在哪里,一般来说,一个scrapy 的项目结构是这样的

scrapydownloadertest  # 项目文件夹
    │  items.py       # 定义爬取结果存储的数据结构
    │  middlewares.py  # 中间件(可以理解java的过滤器拦截器)
    │  pipelines.py   # 数据管道,对获取到的数据做操作
    │  settings.py   # 项目的配置文件
    │  __init__.py   # 初始化逻辑
    │
    ├─spiders  # 放置 Spiders 的文件夹
    │  │  httpProxyIp.py   # 爬取到结果后的处理类
    │  │  __init__.py    # spider初始化逻辑
scrapy.py

从上图可以发现,代理ip的设置肯定是在发送请求之前就要设置好,那么唯一符合条件的地方就是middlewares.py,所以关于代理的相关逻辑都写在这个里面。直接在其中添加如下代码

# Scrapy 内置的 Downloader Middleware 为 Scrapy 供了基础的功能,
# 定义一个类,其中(object)可以不写,效果一样
class SimpleProxyMiddleware(object):
    # 声明一个数组
    proxyList = ['http://218.75.158.153:3128','http://188.226.141.61:8080']
    
    # Downloader Middleware的核心方法,只有实现了其中一个或多个方法才算自定义了一个Downloader Middleware
    def process_request(self, request, spider):
        # 随机从其中选择一个,并去除左右两边空格
        proxy = random.choice(self.proxyList).strip()
        # 打印结果出来观察
        print("this is request ip:" + proxy)
        # 设置request的proxy属性的内容为代理ip
        request.meta['proxy'] = proxy

    # Downloader Middleware的核心方法,只有实现了其中一个或多个方法才算自定义了一个Downloader Middleware
    def process_response(self, request, response, spider):
        # 请求失败不等于200
        if response.status != 200:
            # 重新选择一个代理ip
            proxy = random.choice(self.proxyList).strip()
            print("this is response ip:" + proxy)
            # 设置新的代理ip内容
            request.mete['proxy'] = proxy
            return request
        return response

这样就完成了scrapy的代理设置和验证调试。
那应该如何使用动态代理ip呢?
这里使用的是收费的代理ip了,你可以使用亿牛云等云服务商提供的服务,当你注册并缴费之后,会给你提供代理参数,这里直接看代码吧!

import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.methods.GetMethod;

import java.io.IOException;

public class Main {
    # 代理服务器(产品官网 www.16yun.cn)
    private static final String PROXY_HOST = "t.16yun.cn";
    private static final int PROXY_PORT = 31111;

    public static void main(String[] args) {
        HttpClient client = new HttpClient();
        HttpMethod method = new GetMethod("https://httpbin.org/ip");

        HostConfiguration config = client.getHostConfiguration();
        config.setProxy(PROXY_HOST, PROXY_PORT);

        client.getParams().setAuthenticationPreemptive(true);

        String username = "16ABCCKJ";
        String password = "712323";
        Credentials credentials = new UsernamePasswordCredentials(username, password);
        AuthScope authScope = new AuthScope(PROXY_HOST, PROXY_PORT);

        client.getState().setProxyCredentials(authScope, credentials);

        try {
            client.executeMethod(method);

            if (method.getStatusCode() == HttpStatus.SC_OK) {
                String response = method.getResponseBodyAsString();
                System.out.println("Response = " + response);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            method.releaseConnection();
        }
    }
}

最后我们可以通过访问http://httpbin.org/ip来验证代理ip是否使用成功。