目录
一、动态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)网络波动或禁止访问,导致爬取内容可能重复。因此要判断当前内容是否已经出现,否则一直等待。