使用Tor代理的多线程爬虫

3

我正在尝试构建一个使用Tor代理的多线程爬虫: 我使用以下方法来建立Tor连接:

from stem import Signal
from stem.control import Controller
controller = Controller.from_port(port=9151)
def connectTor():
    socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, "127.0.0.1", 9150)
    socket.socket = socks.socksocket


def renew_tor():
    global request_headers
    request_headers = {
        "Accept-Language": "en-US,en;q=0.5",
        "User-Agent": random.choice(BROWSERS),
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
        "Referer": "http://thewebsite2.com",
        "Connection": "close"
    }

    controller.authenticate()
    controller.signal(Signal.NEWNYM)

以下是URL获取器:

def get_soup(url):
    while True:
        try:
            connectTor()
            r = requests.Session()
            response = r.get(url, headers=request_headers)
            the_page = response.content.decode('utf-8',errors='ignore')
            the_soup = BeautifulSoup(the_page, 'html.parser')
            if "captcha" in the_page.lower():
                print("flag condition matched while url: ", url)
                #print(the_page)
                renew_tor()
            else:
                return the_soup
                break
        except Exception as e:
            print ("Error while URL :", url, str(e))

我正在创建一个多线程抓取任务:
with futures.ThreadPoolExecutor(200) as executor:
            for url in zurls:
                future = executor.submit(fetchjob,url)

然后我遇到了以下错误,但是在使用多进程时我没有看到这个错误:
 Socket connection failed (Socket error: 0x01: General SOCKS server failure)

我希望您能提供任何建议,以避免出现袜子错误,并改善爬取方法的性能,使其支持多线程。


这个解决了吗?https://dev59.com/Hofca4cB1Zd3GeqPdg79 - AmourK
虽然我的代码受到链接中代码的启发,但我试图构建多线程代码,所以我遇到了一个问题。 - user5236897
1个回答

3

这是为什么猴子补丁 socket.socket 是不好的完美例子。

这将被所有 socket 连接(大多数情况下)使用的套接字替换为 SOCKS 套接字。

当您稍后尝试连接控制器时,它会尝试使用 SOCKS 协议进行通信,而不是建立直接连接。

既然您已经在使用 requests,我建议摆脱 SocksiPy 和 socks.socket = socks.socksocket 代码,并使用内置于 requests 中的 SOCKS 代理 功能:

proxies = {
    'http': 'socks5h://127.0.0.1:9050',
    'https': 'socks5h://127.0.0.1:9050'
}

response = r.get(url, headers=request_headers, proxies=proxies)

非常感谢,这解决了套接字问题,但是现在我遇到了(由SSLError(SSLError(“bad handshake:SysCallError(-1,'Unexpected EOF')”,))引起的)问题。 - user5236897
这个错误是否与请求获取URL有关?如果您只尝试通过SOCKS代理向目标站点发出一个请求,那会发生什么? - drew010
这个错误并不总是发生。许多线程都成功了。即使我在单线程模式下运行,有时也会出现这个错误。然而,由于我已经使 get_soup() 方法具有弹性,我仍然能够进行爬取。 - user5236897

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接