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请求库)