Selenium爬取代理网站、并用于图片下载

用Selenium X Requests进行站点图库爬取。

结合多线程、Requests库、Selenium综合爬虫测试。

编写代理自动获取并检测函数。

  • 用到的包。

    # Selenium核心和设置
    from selenium import webdriver
    from selenium.webdriver.chrome.options import Options
    # Requests库和异常库
    import requests
    from requests.exceptions import *
    # 线程管理,使用多线程
    import time
    from threading import Thread
    
  • 项目主要结构。

    proxiestest.py
    access_list=[]  #全局变量
    def proxy_get(base_url,test_url):
        '''
        主要进行爬取工具函数,用于提交test_proxy任务。
        '''
        pass
    def test_proxy(test_url,li,headers):
        '''
        测试代理的函数
        '''
        pass
    if __name__ == "__main__":
        pass
    
  • 封装主函数,进行一些初始化操作。

    access_list=[]  #全局变量,可用列表,如果可用放在这里
    def proxy_get(base_url,test_url):
        '''
        base_url - 爬取的目标网址
        test_url - 测试是否畅通的网站,就相当于ping这个网站吧。
        '''
        chrome_options = Options()
        chrome_options.add_argument('--headless')
        browser = webdriver.Chrome(r'F:\study_project\webpack\SeleniumDemo\chromedriver.exe',chrome_options = chrome_options)
        headers = {
            'Host': 'wx2.sinaimg.cn',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                          'Chrome/61.0.3163.100 Safari/537.36 '
        }
        browser.get(base_url)
        browser.implicitly_wait(10)
        time.sleep(5)
    
  • 爬取逻辑,循环添加线程,提交test_proxy()任务。然后阻塞,防止主线程关闭导致子线程关闭。

    def proxy_get(base_url,test_url):
        ... ...(继承上面代码)
        tr = browser.find_elements_by_xpath('//tr')     # 匹配全部列表项
        current_list=[] #用来装获取到的ip:port列表
        i=1
        for td in tr:
            ip=browser.find_element_by_xpath('//tr[{}]/td[1]'.format(i)).text   #第一项是ip
            port=browser.find_element_by_xpath('//tr[{}]/td[2]'.format(i)).text #第二项是port
            current_list.append('{}:{}'.format(ip,port))
            print('{}:{}'.format(ip,port))
            i+=1
            if i==len(tr):
                break
    
        # 线程列表,用于多线程检测可用性。
        thread_list=[]
        for li in current_list:
            # target=test_proxy,这个函数下面写。
            t=Thread(target=test_proxy,args=(test_url,li,headers)) 
            thread_list.append(t)
            t.start()
        # 阻塞所有线程,防止主线程关闭。最主要的是保证access_list全局变量里有东西。
        for thread in thread_list:
            thread.join()
    
        print('{}个代理可以使用,一共检测到{}个代理。'.format(len(access_list),len(current_list)))
        return access_list  #返回这个全局变量。包含全部可用代理。
    
  • 任务函数。用于检测代理可用性。

    def test_proxy(test_url,li,headers):
        global access_list   #使用全局变量。
        proxy_temp={"http":li}
        try:
            res = requests.get(test_url,headers=headers,proxies=proxy_temp,verify=False,timeout=5).status_code
            access_list.append(proxy_temp)      # 如果成功加入列表。
        except Exception as e:
            print(li+"  is delete"+'-------')  # 如果异常就删除这个代理。
            print(e)
    
  • 编写主函数用于测试一下~

    if __name__ == "__main__":
        # https://ip.ihuan.me/
        ip_list=proxy_get('https://ip.ihuan.me/','http://jandan.net/ooxx')  #https://www.kuaidaili.com/free/inha/
        for i in ip_list:
            print(i)
        print(random.choice(ip_list))
    

编写图片爬取代码,并使用刚才的代理。

  • 用到包

    # Selenium主要工具类和Requests库,以及ssl验证
    from selenium import webdriver
    from selenium.webdriver.chrome.options import Options
    import requests
    from requests.exceptions import *
    import ssl
    # 仍然采用多线程下载。但是注意不要多线程嵌套多线程。代理要在主函数里获取好(废话)。
    import time
    import threading
    import random
    
  • 项目主要结构。

    restructure.py
    
    # 3. 下载图片
    def download_pic(url,proxy_ip=""):
        pass
    # 2. 翻页下载,循环调用这个函数。
    def request_start(browser,base_url,proxies_list=[]):
        pass
    # 1. 初始化请求、代理,调用翻页下载。
    def browser_get(base_url='http://jandan.net/ooxx',proxy_url='https://www.kuaidaili.com/free/inha/',test_url=base_url):
        pass
    if __name__ == "__main__":
        pass
    
  • 初始化方法的一些设置。

    def browser_get(base_url='http://jandan.net/ooxx',proxy_url='https://www.kuaidaili.com/free/inha/',test_url=base_url):
        '''
        base_url - 爬取目标的url
        proxy_url - 获取代理的页面。
        test_url - 测试代理是否可用的页面。默认直接用目标的url,的确也应该这样....
        '''
        chrome_options = Options()
        # 不加载图片和css,这样更快,因为我们使用下载函数时再进行下载。
        prefs = {"profile.managed_default_content_settings.images": 2,'permissions.default.stylesheet':2}
        chrome_options.add_experimental_option('prefs', prefs)
        #使用手机模式
        chrome_options.add_experimental_option("mobileEmulation", { "deviceName": "Nexus 5" })
        #为了更好监控,我们关闭隐模式
        #chrome_options.add_argument('--headless')
        browser = webdriver.Chrome(r'F:\study_project\webpack\SeleniumDemo\chromedriver.exe',chrome_options = chrome_options)
        
        browser.get(base_url)
        browser.implicitly_wait(10)
        # 这句主要是让页面可以加载加载...
        js="document.documentElement.scrollTop="+ str(500) 
        browser.execute_script(js)
        time.sleep(2)
    
  • 初始化代理设置,直接把代理列表整理好。

    def browser_get(base_url='http://jandan.net/ooxx',proxy_url='https://www.kuaidaili.com/free/inha/',test_url=base_url):
        ... ...(继承上面函数)
        from proxiestest import proxy_get
        proxies_list=proxy_get(proxy_url,test_url)  #这个函数是我们例1中的代理获取函数。
        choice_ip=""
        if len(proxies_list)!=0:
            choice_ip=random.choice(proxies_list)   #有可能获取的代理全都不能用。这时候返回空列表,使用本机代理。或者...别搞了。
    
  • 匹配全部图片url:

    def browser_get(base_url='http://jandan.net/ooxx',proxy_url='https://www.kuaidaili.com/free/inha/',test_url=base_url):
        ... ...(继承上面函数)
        ul = browser.find_elements_by_xpath('//a[@class="view_img_link"]')  # 匹配全部携带图片url的a标签
        threads_list=[]
        # 为每一个下载任务匹配一个代理。
        for li in ul:
            choice_ip=""
            if len(proxies_list)!=0:
                choice_ip=random.choice(proxies_list)
            #多线程提交任务,download_pic后面写。
            t=threading.Thread(target=download_pic,args=(li.get_attribute("href"),choice_ip))
            threads_list.append(t)
            t.start()
        # 还是阻塞一下,防止主函数读取不到配置。
        for i in threads_list:
            i.join()
        # 调用这个函数进行翻页。
        request_start(browser,base_url,proxies_list)
    
  • 翻页函数处理。找到翻页按钮,然后单击进行下一页。这个函数其实可以新一步封装。因为下面都是一样的。

    def request_start(browser,base_url,proxies_list=[]):
        '''
        browser - 浏览器对象
        base_url - 好像没什么用了。
        proxies_list - 把获取到的代理列表传进去。
        '''
    
        js="document.documentElement.scrollTop="+ str(8000)
        browser.execute_script(js)
        time.sleep(2)
        
        element=browser.find_element_by_xpath('//a[@title="Older Comments"][1]')
        print('text--------{}'.format(element.text))
        # 如果下一页存在就单击下一页。
        if element:
            element.click()
            time.sleep(10)
        else:
            return "已经没有啦"
        
        #下面的逻辑就和上面一样了。最后调用自己无限翻页。
        ul = browser.find_elements_by_xpath('//a[@class="view_img_link"]')  # 匹配全部携带图片url的a标签
        threads_list=[]
        # 为每一个下载任务匹配一个代理。
        for li in ul:
            choice_ip=""
            if len(proxies_list)!=0:
                choice_ip=random.choice(proxies_list)
            #多线程提交任务,download_pic后面写。
            t=threading.Thread(target=download_pic,args=(li.get_attribute("href"),choice_ip))
            threads_list.append(t)
            t.start()
        # 还是阻塞一下,防止主函数读取不到配置。
        for i in threads_list:
            i.join()
        # 调用这个函数进行翻页。
        request_start(browser,base_url,proxies_list)
    
  • 最后是下载函数部分。

    # 下载图片
    def download_pic(url,proxy_ip=""):
        correct_url = url
        if url.startswith('//'):
            correct_url = url[2:]
        if not url.startswith('http'):
            correct_url = 'http://' + correct_url
        print(correct_url)
        headers = {
            'Host': 'wx2.sinaimg.cn',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                          'Chrome/61.0.3163.100 Safari/537.36 '
        }
        proxies=proxy_ip
        try:
            resp=None
            if proxies=="":
                resp=requests.get(correct_url,headers=headers,verify=False,timeout=2)
            else:
                print('proxy={}'.format(proxies))
                resp=requests.get(correct_url,proxies = proxies,headers=headers,verify=False,timeout=2)
            pic = resp.content
            pic_name = correct_url.split("/")[-1]
            with open('output/JianDan/' + pic_name, "wb+") as f:
                f.write(pic)
        except (ReadTimeout,Timeout,ConnectionError,RequestException, Exception) as reason:
            print(str(reason))
    
  • 编写主函数测试!

    if __name__ == "__main__":
        ssl._create_default_https_context = ssl._create_unverified_context
        browser_get(base_url='http://jandan.net/ooxx',proxy_url='https://ip.ihuan.me/',test_url='http://jandan.net/ooxx')
    

Reference:
https://www.cnblogs.com/tinghai8/p/9217544.html (python3 request 库)
https://www.cnblogs.com/linxiyue/p/3980003.html (Python Requests库:HTTP for Humans)
https://www.cnblogs.com/tinghai8/p/9051513.html (python3下urllib.request库高级应用之ProxyHandler处理器(代理设置))
https://www.cnblogs.com/tinghai8/p/9044189.html (python3下urllib.request库高级应用之Handle处理器和自定义Opener)
https://www.cnblogs.com/tinghai8/p/9041213.html (Python3处理HTTPS请求 SSL证书验证)
https://www.cnblogs.com/ShenJunHui6/p/10941019.html (requests请求库)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值