稳定对抗反爬虫机制:完整代码及注释
要稳定对抗反爬虫机制,可以尝试以下几个措施:
-
使用代理IP:使用代理IP可以隐藏真实IP地址,增加爬取的隐蔽性。您可以使用第三方代理服务提供商的代理IP,确保在每次请求中使用不同的IP地址。
-
设置请求头信息:除了随机的User-Agent之外,还可以设置其他请求头信息,如Referer、Accept-Language等,以模拟真实的浏览器访问行为。
-
使用会话保持持久连接:使用'requests.Session()'创建一个会话,并在多个请求中保持持久连接。这样可以模拟连续的浏览行为,降低被反爬虫识别的可能性。
-
添加随机延迟:在每次请求之间添加随机的延迟,模拟真实用户的浏览行为,避免频繁请求被识别为爬虫。
下面是添加了以上措施的完整代码,并注释了相关部分:
import requests
from bs4 import BeautifulSoup
import time
import tkinter as tk
import webbrowser
import random
import os
import re
def get_random_user_agent():
user_agents = [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36',
]
return random.choice(user_agents)
def get_random_proxy():
# 返回代理IP列表,每次请求时使用不同的代理IP
proxies = [
'http://proxy1.example.com',
'http://proxy2.example.com',
'http://proxy3.example.com',
]
return random.choice(proxies)
def crawl_baidu(keyword, page_limit):
headers = {
'User-Agent': get_random_user_agent(),
'Referer': 'https://www.baidu.com/',
'Accept-Language': 'en-US,en;q=0.9',
}
results = []
session = requests.Session() # 创建会话对象
for page in range(1, page_limit + 1):
url = f'https://www.baidu.com/s?wd={keyword}&pn={(page - 1) * 10}'
# 添加随机延迟
delay = random.uniform(0.5, 1.0)
time.sleep(delay)
try:
proxy = get_random_proxy() # 获取随机代理IP
response = session.get(url, headers=headers, proxies={'http': proxy})
response.raise_for_status() # 检查请求是否成功
soup = BeautifulSoup(response.text, 'html.parser')
for result in soup.find_all('div', class_='result'):
result_title = result.find('h3').get_text()
result_url = result.find('a')['href']
results.append((result_title, result_url))
except requests.exceptions.RequestException as e:
print(f'请求异常: {e}')
return results
def open_url(url):
webbrowser.open(url)
def crawl_and_index():
keywords = re.split(r'[,,\s]+', entry_keywords.get()) # 获取关键词列表
page_limit = int(entry_pages.get()) # 获取指定的爬取页数
# 创建文件夹用于保存网页文件
if not os.path.exists('webpages'):
os.makedirs('webpages')
# 爬取并保存网页文件
for keyword in keywords:
search_results = crawl_baidu(keyword, page_limit)
if len(search_results) > 0:
file_name = f'webpages/{keyword}.html'
with open(file_name, 'w', encoding='utf-8') as file:
file.truncate(0) # 清空文件内容
for title, url in search_results:
file.write(f'{title}\n')
file.write(f'{url}\n')
file.write('\n')
else:
print(f'关键词 '{keyword}' 没有搜索结果')
def search_local():
keyword = entry_search.get()
result_text.delete('1.0', tk.END)
# 遍历网页文件,搜索匹配的结果
for file_name in os.listdir('webpages'):
with open(f'webpages/{file_name}', 'r', encoding='utf-8') as file:
lines = file.readlines()
# 确保行数足够
if len(lines) < 2:
continue
found_results = {}
for i in range(0, len(lines), 2):
if i + 1 >= len(lines):
break
title = lines[i].strip()
url = lines[i + 1].strip()
if keyword.lower() in title.lower() or keyword.lower() in url.lower():
found_results[len(found_results) + 1] = (title, url)
if len(found_results) > 0:
result_text.insert(tk.END, f'搜索结果 - {file_name[:-5]}:\n\n', 'title')
for index, (title, url) in found_results.items():
result_text.insert(tk.END, f'{title}\n', 'found_title')
result_text.insert(tk.END, f'{url}\n', f'link{index}')
result_text.tag_configure(f'link{index}', foreground='blue', underline=True)
result_text.tag_bind(f'link{index}', '<Button-1>', lambda event, url=url: open_url(url))
result_text.insert(tk.END, '\n')
if result_text.get('1.0', tk.END) == '\n':
result_text.insert(tk.END, '没有搜索结果\n')
# 创建UI界面
window = tk.Tk()
window.title('百度搜索')
window.geometry('800x600')
label_keywords = tk.Label(window, text='请输入关键词(用逗号或空格隔开):')
label_keywords.pack()
entry_keywords = tk.Entry(window)
entry_keywords.pack()
label_pages = tk.Label(window, text='请输入爬取页数:')
label_pages.pack()
entry_pages = tk.Entry(window)
entry_pages.pack()
crawl_button = tk.Button(window, text='爬取并索引', command=crawl_and_index)
crawl_button.pack()
label_search = tk.Label(window, text='请输入搜索关键词:')
label_search.pack()
entry_search = tk.Entry(window)
entry_search.pack()
search_button = tk.Button(window, text='搜索', command=search_local)
search_button.pack()
scrollbar = tk.Scrollbar(window)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
result_text = tk.Text(window, yscrollcommand=scrollbar.set)
result_text.pack(fill=tk.BOTH)
scrollbar.config(command=result_text.yview)
window.mainloop()
请注意,这些措施可以提高爬取的稳定性和抵抗反爬虫的能力,但不能保证绝对的成功。实际应用中,仍可能遇到其他反爬虫措施或限制。因此,根据具体情况,您可能需要进一步调整代码,并考虑使用更高级的反反爬虫技术,如使用验证码识别、使用分布式爬虫等。
原文地址: https://www.cveoy.top/t/topic/SQf 著作权归作者所有。请勿转载和采集!