0


【Python爬虫】动态IP+多线程下载+Selenium

一、动态IP

    首先介绍动态IP的重要性。

    在数据量较小的情况下,本地IP访问量不大,不会出现问题。但是在数据量较大的情况下,如果不采用动态IP的问题,那么会导致IP被对方网站拉黑,甚至在浏览器都打不开对方网址,更不要说爬虫或下载任务。因此,IP代理十分重要。

1. 三种代理模式

(1) 透明代理

    代理服务器将客户端的信息转发至目标访问对象,并没有完全隐藏客户端真实的身份。即服务器知道客户端使用了代理IP,并且知道客户端的真实IP地址。

(2) 普通匿名代理

    代理服务器用自己的IP代替了客户端的真实IP,但是告诉了目标访问对象这是代理访问。

(3) 高匿代理

    代理服务器良好地伪装了客户端,不但用一个随机的IP代替了客户端的IP,也隐藏了代理信息,服务器不会察觉到客户端是通过代理实现访问的,即用户仿佛就是直接使用代理服务器作为自己的客户端。

    爬虫时,需要使用高匿代理。

2. 实用代理平台

    代理IP的平台很多,较为正式且实测有效的是一种资源。2个较为全面的介绍如下:

    ①https://zhuanlan.zhihu.com/p/290719786

    ②https://zhuanlan.zhihu.com/p/33576641

     代理可分为2大类:IP池和隧道代理。

    IP池可以认为是存储很多可用IP的池子,需要时把IP拿出来使用。

    隧道代理则是提供一个隧道,隧道那端自动切换IP返回。

    由此可知,**爬虫时主要使用隧道代理**。

(1)快代理

    经过测试,快代理可以正常使用,但无法访问国外网站,甚至有些在国内可以访问的国外网址都无法访问(没有测试过快代理的隧道代理是否也有这个问题)。

(2)小象代理

     经过测试,小象代理可以正常使用。

3. 测试代理IP能不能用

# 测试代理IP能不能用
# print(requests.get('http://httpbin.org/ip', proxies=proxies, timeout=5).text)

4. 伪装请求头User-Agent

from fake_useragent import UserAgent
# 随机请求头
headers = {'User-Agent':UserAgent().random}
res = requests.get(url,headers = headers,proxies = proxies)
     查看自己浏览器版本和请求头:浏览器输入**about:version**


二、多线程下载

    在得到目标url后,需要批量下载。下载方式有很多:多协程、多线程、多进程。

    可能本人对协程理解不深,使用时经常出现一些问题:如下载图片损坏等。可以部分参考本人之前博客(亲测有效)selenium+python爬虫实用技巧_uestc_hjw的博客-CSDN博客。

    实际使用的是多线程下载。
import requests
from multiprocessing.pool import ThreadPool # 线程池:使用方法和Pool一样
# from multiprocessing.dummy import Pool as ThreadPool # 两种线程池都可以
# from multiprocessing import Pool # 进程池
# 进程教程:https://docs.python.org/zh-cn/3/library/multiprocessing.html
import os
from tqdm import tqdm
from fake_useragent import UserAgent

def download():
    txt_path = './Data.txt'
    Img_path = './Images/'
    thread_num = 16 # 线程数
    os.makedirs(Img_path,exist_ok=True)
    # 所有要下载的数量
    with open(txt_path,'r') as f:
        datas = f.readlines()
    ''' 中间的处理步骤 '''
    ''' 要达成的效果:datas是一个list:第一项是url, 第二项是保存路径 '''
    datas = [['url1','save_path1'],['url2','save_path2'],...]
    # 多线程下载
    gg = ThreadPool(thread_num).imap_unordered(download_one,datas)
    for _ in tqdm(gg):
        pass

def download_one(data):
    name = 'xx' # 文件名
    try:
        # session = requests.Session()
        while 1:
            res = requests.get(data[0],headers = headers,proxies = proxies)
            if res.status_code == 200: # 200是正常访问
                break
            if res.status_code == 500: # 除了503问题外,对方网站可能出现500问题,即他的问题,所以一直等就卡着了
                with open(f'./No_content_{name}.txt','a') as f:
                    f.write(data[0] + '!!' + data[1] +'\n')
                return 0
        img = res.content
        if len(img)>5000:
            with open(data[1],'wb') as f:
                f.write(img)
        else:
            with open(f'./No_content_{name}.txt','a') as f:
                f.write(data[0] + '!!' + data[1] +'\n')
    except:
        pass

if __name__ == '__main__':
    download()

三、Selenium爬虫

1. 爬取班级同学的录取情况

任务说明:根据excel提供的班级花名册,在网页上找到同学的录取信息


(1)提取Excel

roster_path = r'D:\2022秋季学期课程\2022级人工智能学院1603班花名册.xlsx'
web_path = "http://ia.cas.cn/yjsjy/zs/sszs/202110/t20211009_6219697.html"
roster = pandas.read_excel(roster_path)
data = roster.iloc[:,3].values[1:]
print(data)

(2)网页信息示意

url:2022年自动化所推免直博和硕士生拟录取名单公示----自动化研究所 (cas.cn)


(3)完整代码

import pandas
import time
import numpy as np

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By

# chrome version: 105.0.5195.127
roster_path = r'D:\2022秋季学期课程\2022级人工智能学院1603班花名册.xlsx'
web_path = "http://ia.cas.cn/yjsjy/zs/sszs/202110/t20211009_6219697.html"
roster = pandas.read_excel(roster_path)
data = roster.iloc[:,3].values[1:]
print(data)

output_path = r'D:\Vscode_Programming_Set\WebCrawler\Find_Classmates_of_1603.xlsx'
def Find_Classmates(web_path:str,data:list,output_path:str):
    options = webdriver.ChromeOptions()
    User_Agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.5195.127 Safari/537.36 Edg/96.0.1054.57'
    options.add_argument('user-agent=' + User_Agent)     # UA代理
    options.add_argument("--window-size=1920,1080")
    options.add_experimental_option('excludeSwitches', ['enable-automation'])
    options.add_argument('--disable-gpu')
    browser = webdriver.Chrome(options=options,service = Service(r'D:\chromedriver\chromedriver.exe'))
    browser.get(web_path)
    name_list = browser.find_elements(By.XPATH,'//*[@id="zoom"]/div/div/table/tbody/tr')
    #                                           //*[@id="zoom"]/div/div/table/tbody/tr[2]/td[1]
    result = []
    for i in name_list:
        name = i.find_element(By.XPATH,'.//td[1]').text
        if name in data:
            result.append([name,i.find_element(By.XPATH,'.//td[2]').text,i.find_element(By.XPATH,'.//td[3]').text,i.find_element(By.XPATH,'.//td[4]').text,i.find_element(By.XPATH,'.//td[8]').text])

    df = pandas.DataFrame(result,columns=['Name','admission_type','Gender','School','Tutor'])
    df.to_excel(output_path,index=False)

Find_Classmates(web_path,data,output_path)

(4)实现效果


四、常用操作与个人经验

**1. **遍历list下的内容

name_list = browser.find_elements(By.XPATH,'//*[@id="zoom"]/div/div/table/tbody/tr')
#                                           //*[@id="zoom"]/div/div/table/tbody/tr[2]/td[1]
result = []
for i in name_list:
    name = i.find_element(By.XPATH,'.//td[1]').text  # 这个.很重要

2. 个人经验

(1)requests.get()正常返回200,但也会出现500,即对方错误,和url本身就不存在图像的可能。因此要判断len(content)的大小,符合要求再下载。

(2)网络波动或禁止访问,导致爬取内容可能重复。因此要判断当前内容是否已经出现,否则一直等待。

标签: selenium 爬虫 python

本文转载自: https://blog.csdn.net/zhengyuyin/article/details/126886715
版权归原作者 uestc_hjw 所有, 如有侵权,请联系我们删除。

“【Python爬虫】动态IP+多线程下载+Selenium”的评论:

还没有评论