【问题标题】:Unable to pass proxies and links to the threadpool to get results无法将代理和链接传递到线程池以获取结果
【发布时间】:2019-05-25 01:32:28
【问题描述】:

我在 python 中编写了一个脚本,使用 代理 来抓取遍历网页不同页面的不同帖子的链接。我尝试使用列表中的proxies。该脚本应该从列表中随机获取proxies 并向该网站发送请求,最后解析这些项​​目。但是,如果任何proxy 不起作用,则应将其从列表中踢出。

我认为我在ThreadPool(10).starmap(make_requests, zip(proxyVault,lead_url)) 中使用number of proxieslist of urls 的方式是准确的,但它不会产生任何结果;相反,脚本卡住了。

如何将代理和链接传递给 ThreadPool 以使脚本产生结果?

import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin
from multiprocessing.pool import ThreadPool
from itertools import cycle
import random

base_url = 'https://stackoverflow.com/questions/tagged/web-scraping'
lead_url = ["https://stackoverflow.com/questions/tagged/web-scraping?sort=newest&page={}&pagesize=15".format(page) for page in range(1,6)]

proxyVault = ['104.248.159.145:8888', '113.53.83.252:54356', '206.189.236.200:80', '218.48.229.173:808', '119.15.90.38:60622', '186.250.176.156:42575']

def make_requests(proxyVault,lead_url):
    while True:
        random.shuffle(proxyVault)
        global pitem   
        pitem = cycle(proxyVault)
        proxy = {'https':'http://{}'.format(next(pitem))}
        try:
            res = requests.get(lead_url,proxies=proxy)
            soup = BeautifulSoup(res.text,"lxml")
            [get_title(proxy,urljoin(base_url,item.get("href"))) for item in soup.select(".summary .question-hyperlink")]
        except Exception:
            try: 
                proxyVault.pop(0)
                make_requests(proxyVault,lead_url)
            except Exception:pass

def get_title(proxy,itemlink):
    res = requests.get(itemlink,proxies=proxy)
    soup = BeautifulSoup(res.text,"lxml")
    print(soup.select_one("h1[itemprop='name'] a").text)

if __name__ == '__main__':
    ThreadPool(10).starmap(make_requests, zip(proxyVault,lead_url))

顺便说一句,上面使用的proxies 只是占位符。

【问题讨论】:

    标签: python python-3.x web-scraping proxy


    【解决方案1】:

    您的代码的问题在于它在线程中创建了许多无限循环。他们处理代理的方式对我来说有点奇怪,所以我改变了它。 我还认为您误解了数据是如何发送到线程的,它们获得了可迭代的一个元素,而不是整个元素。所以我改变了一些名字来反映这一点。

    现在的工作方式是每个线程从lead_url获取自己的url,然后从proxyVault中选择一个随机代理。 他们获取网页并对其进行解析,并在每个解析的链接上调用 get_title。

    如果请求因代理而失败,则从列表中删除该代理,使其不再使用,并再次调用 make_requests,这将从仍然可用的代理中随机选择一个新代理。 我没有改变实际的解析,因为我无法判断它是否是你想要的。

    可运行代码:

    https://repl.it/@zlim00/unable-to-pass-proxies-and-links-to-the-threadpool-to-get-re

    from bs4 import BeautifulSoup
    from multiprocessing.pool import ThreadPool
    from random import choice
    import requests
    from urllib.parse import urljoin
    
    base_url = 'https://stackoverflow.com/questions/tagged/web-scraping'
    lead_url = [f'https://stackoverflow.com/questions/tagged/web-scraping?sort='
                f'newest&page={page}&pagesize=15' for page in range(1, 6)]
    
    proxyVault = ['36.67.57.45:53367', '5.202.150.233:42895',
                  '85.187.184.129:8080', '109.195.23.223:45947']
    
    def make_requests(url):
        proxy_url = choice(proxyVault)
        proxy = {'https': f'http://{proxy_url}'}
        try:
            res = requests.get(url, proxies=proxy)
            soup = BeautifulSoup(res.text, "lxml")
            [get_title(proxy, urljoin(base_url, item.get("href")))
             for item in soup.select(".summary .question-hyperlink")]
        except requests.exceptions.ProxyError:
            # Check so that the bad proxy was not removed by another thread
            if proxy_url in proxyVault:
                proxyVault.remove(proxy_url)
                print(f'Removed bad proxy: {proxy_url}')
            return make_requests(url)
    
    def get_title(proxy, itemlink):
        res = requests.get(itemlink, proxies=proxy)
        soup = BeautifulSoup(res.text, "lxml")
        print(soup.select_one("h1[itemprop='name'] a").text)
    
    if __name__ == '__main__':
        ThreadPool(10).map(make_requests, lead_url)
    

    【讨论】:

    • 迄今为止我遇到的最好的脚本@SimonF。唯一的问题是您的脚本一直在运行并产生重复,因为它无法在时间到时跳出循环。但是,它仍然是我经验中最好的。我希望你能解决这个缺点。谢谢。
    • @robots.txt 你能举一个重复的例子吗?解析页面的逻辑是你的,我没有改变它。当您抓取的所有标题都打印出来时,脚本会停止,但它需要一些时间,因为您首先需要链接请求,然后每个标题都需要另一个请求。
    • 跑完后我会告诉你结果。再次感谢一万亿@SimonF。
    • 嗨@SimonF,如果有什么可以解决的问题,请查看this post。提前致谢。
    【解决方案2】:

    也许您可以使用另一种方法来获取这样的代理

    def get_proxy():                                                                                                                                                                                  
        url = 'https://free-proxy-list.net/anonymous-proxy.html'                                                                                                                                      
        response = requests.get(url)                                                                                                                                                                  
        soup = BeautifulSoup(response.text, 'lxml')                                                                                                                                                   
        table = soup.find('table', attrs={'id': 'proxylisttable'})                                                                                                                                    
        table_body = table.find('tbody')                                                                                                                                                              
        proxies = table_body.find_all('tr')                                                                                                                                                           
        proxy_row = random.choice(proxies).find_all('td')                                                                                                                                             
        return proxy_row[0].text + ':' + proxy_row[1].text  
    

    【讨论】:

    • 我的问题不是关于获取代理;而是关于以正确的方式使用它们@user1330614。
    猜你喜欢
    • 2020-01-18
    • 1970-01-01
    • 2022-09-25
    • 1970-01-01
    • 2011-06-01
    • 1970-01-01
    • 2014-11-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多