爬虫与反爬虫之间的斗争
爬虫的建议
- 尽量减少请求次数
- 能抓取列表⻚就不抓详情⻚
- 保存获取到的HTML,供查错和重复使⽤
- 关注⽹站的所有类型的⻚⾯
- H5页面
- APP
- 多伪装
- 代理IP
- 不适用cookie
- 利用多线程分布式
- 在不被禁的请求下尽可能的提高速度
动态HTML技术了解
-
JS
- 是⽹络上最常⽤的脚本语⾔,它可以收集⽤户的跟踪数据,不需要重载⻚ ⾯直接提交表单,在⻚⾯嵌⼊多媒体⽂件,甚⾄运⾏⽹⻚
-
jQuery
- jQuery是⼀个快速、简介的JavaScript框架,封装了JavaScript常⽤的 功能代码
-
ajax
- ajax可以使⽤⽹⻚实现异步更新,可以在不重新加载整个⽹⻚的情况下,对⽹⻚的某部分进⾏更新
获取ajax数据的方式
- 直接分析ajax调⽤的接⼝。然后通过代码请求这个接⼝。
- 使⽤Selenium+chromedriver模拟浏览器⾏为获取数据
| 方式 | 优点 | 缺点 |
|---|---|---|
| 分析接口 | 直接可以请求到数据.不需要做一下解析工作,代码量少,性能高 | 分析接口比较复杂,特别是一些通过js混淆的接口,要有一定的js功底.容易被发现是爬虫 |
| selenium | 直接模拟浏览器的行为.浏览器能请求到的,使用selenium也能请求到.爬虫更稳定 | 代码量多,性能低 |
Selenium
selenium是⼀个web的⾃动化测试⼯具,最初是为⽹站⾃动化测试⽽开发的, selenium可以直接运⾏在浏览器上,它⽀持所有主流的浏览器,可以接收指 令,让浏览器⾃动加载⻚⾯,获取需要的数据,甚⾄⻚⾯截屏
chromedriver是⼀个驱动Chrome浏览器的驱动程序,使⽤他才可以驱动浏览器。当然针对不同的浏览器有不同的driver。以下列出了不同浏览器及其对应的driver:
Chrome: sites.google.com/a/chromium.…
chromedriver下载地址:
版本在114及以下:chromedriver.storage.googleapis.com/index.html
版本在127:googlechromelabs.github.io/chrome-for-…
其他版本下载方法:
如版本127.0.6533 32位下载地址是:
其他版本下载地址把上面地址中的版本号替换即可
两个地址都可以下载,根据自己的chrome浏览器的版本选择下载即可
若以上地址不可以,可以尝试: getwebdriver.com/
Firefox:github.com/mozilla/gec…
Edge:developer.microsoft.com/en-us/micro…
Safari:webkit.org/blog/6900/w…
因为我使用的是Anaconda环境,所以可以将下载好的压缩文件解压后复制chromedriver.exe到Anaconda安装目录下的Scripts目录下
# -*- coding: UTF-8 -*-
# @Project :网络爬虫
# @File :selenium入门_01.py
# @IDE :PyCharm
# @Author :艳烔
# @Date :2024/10/27 1:04
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
driver.implicitly_wait(20)
print(driver.title)
driver.close()
或者放到其他文件的目录下,如:D:\Development\
这种方式需要自己在Python程序中指定安装目录
安装Selenium
pip install selenium
Selenium入门
Chrome 浏览器提供了无头模式(headless mode),可以在不打开图形界面的情况下运行浏览器。你可以使用 ChromeDriver 并配置 Chrome 为无头模式。
# -*- coding: UTF-8 -*-
# @Project :网络爬虫
# @File :Phantomjs案例.py
# @IDE :PyCharm
# @Author :艳烔
# @Date :2024/10/27 9:04
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from time import sleep
from selenium.webdriver.common.by import By
# 设置Chrome为无头模式
chrome_options = Options()
chrome_options.add_argument('--headless')
# 创建ChromeDriver实例
driver = webdriver.Chrome(chrome_options)
driver.get("https://www.baidu.com")
print(driver.title)
driver.implicitly_wait(4)
# 定位和操作
driver.find_element('id', 'kw').send_keys('长城')
driver.find_element(By.ID, 'su').click()
driver.implicitly_wait(4)
# 查看请求信息
print(driver.page_source) # 查看网页源码
print(driver.get_cookies()) # 查看cookies
print(driver.current_url) # 查看当前页面的url
driver.quit() # 退出浏览器
参考文档:www.runoob.com/python3/pyt…
要注意, find_element 是获取第⼀个满⾜条件的元素。 find_elements
是获取所有满⾜条件的元素。
操作按钮:操作按钮有很多种⽅式。⽐如单击、右击、双击等。点击,直接调⽤click函数就可以了。
click_and_hold(element):点击但不松开⿏标。
context_click(element):右键点击。
double_click(element):双击。
更多⽅法请参考:selenium-python.readthedocs.io/api.html
# -*- coding: UTF-8 -*-
# @Project :网络爬虫
# @File :登录豆瓣练习_03.py
# @IDE :PyCharm
# @Author :艳烔
# @Date :2024/10/27 9:39
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from time import sleep
# 无界面模式
chrome_options = Options()
chrome_options.add_argument('--headless')
# 打开豆瓣
driver = webdriver.Chrome()
driver.get("https://www.douban.com/")
driver.implicitly_wait(3)
login_frame = driver.find_element(By.XPATH, '//div[@class="login"]/iframe')
# 切换到登录页面
driver.switch_to.frame(login_frame)
driver.find_element(By.CLASS_NAME, 'account-tab-account').click()
driver.find_element(By.ID, 'username').send_keys('15663254155')
driver.find_element(By.ID, 'password').send_keys('123456')
driver.find_element(By.XPATH, '/html/body/div[1]/div[2]/div[1]/div[5]').click()
sleep(3)
# 后面需要滑块验证
driver.quit()
行为链
有时候在⻚⾯中的操作可能要有很多步,那么这时候可以使⽤⿏标⾏为链类 ActionChains来完成。⽐如现在要将⿏标移动到某个元素上并执⾏点击事件。
# -*- coding: UTF-8 -*-
# @Project :网络爬虫
# @File :行为链.py
# @IDE :PyCharm
# @Author :艳烔
# @Date :2024/10/27 10:14
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
driver = webdriver.Chrome()
driver.get('https://www.baidu.com')
inputTag = driver.find_element(By.ID,'kw')
subBtn = driver.find_element(By.ID,'su')
action = ActionChains(driver)
action.move_to_element(inputTag)
action.send_keys_to_element(inputTag,'python')
action.move_to_element(subBtn)
action.context_click() # 右键
action.click(subBtn)
# 提交行为链上的操作
action.perform()
Cookie操作
# -*- coding: UTF-8 -*-
# @Project :网络爬虫
# @File :Cookie操作.py
# @IDE :PyCharm
# @Author :艳烔
# @Date :2024/10/27 10:33
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get('https://www.douban.com')
# 获取所有的cookie
cookies = driver.get_cookies()
for cookie in cookies:
print(cookie)
print("==="*30)
# 根据cookie的name获取cookie的值
print(driver.get_cookie('ll'))
print("==="*30)
# 删除cookie
driver.delete_cookie('ll')
print(driver.get_cookie('ll'))
driver.quit()
页面等待
现在的⽹⻚越来越多采⽤了 Ajax 技术,这样程序便不能确定何时某个元素完全加载出来了。如果实际⻚⾯等待时间过⻓导致某个dom元素还没出来,但是你的代码直接使⽤了这个WebElement,那么就会抛出NullPointer的异常。为了解决这个问题。所以 Selenium 提供了两种等待⽅式:⼀种是隐式等待、⼀种是显式等待
- 隐式等待:调⽤driver.implicitly_wait。那么在获取不可⽤的元素之前,会先等待10秒中的时间。
- 显示等待:显示等待是表明某个条件成⽴后才执⾏获取元素的操作。也可以在等待的时候指定⼀个最⼤的时间,如果超过这个时间那么就抛出⼀个异常。显示等待应该使⽤ selenium.webdriver.support.excepted_conditions期望的条件和 selenium.webdriver.support.ui.WebDriverWait来配合完成。
# -*- coding: UTF-8 -*-
# @Project :网络爬虫
# @File :页面等待.py
# @IDE :PyCharm
# @Author :艳烔
# @Date :2024/10/27 10:45
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
try:
WebDriverWait(driver, 10).until(
EC.presence_of_element_located(
(By.ID, 'kwss')
)
)
finally:
driver.quit()
⼀些其他的等待条件
- presence_of_element_located:某个元素已经加载完毕了。
- presence_of_all_elements_located:⽹⻚中所有满⾜条件的元素都加载完毕了。
- element_to_be_clickable:某个元素是可以点击了。
更多条件请参考:selenium-python.readthedocs.io/waits.html
打开多窗口和切换页面
有时候窗⼝中有很多⼦tab⻚⾯。这时候肯定是需要进⾏切换的。selenium提供 了⼀个叫做switch_to_window来进⾏切换,具体切换到哪个⻚⾯,可以从driver.window_handles中找到。
# -*- coding: UTF-8 -*-
# @Project :网络爬虫
# @File :打开多窗口.py
# @IDE :PyCharm
# @Author :艳烔
# @Date :2024/10/31 8:01
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
driver.execute_script("window.open('https://www.douban.com')")
driver.find_element(By.ID, 'kw').send_keys("python")
print(driver.current_url)
# 切换界面
driver.switch_to.window(driver.window_handles[0])
print(driver.current_url)
time.sleep(10)
# driver.close()
# driver.quit()
模拟QQ邮箱登录
# -*- coding: UTF-8 -*-
# @Project :网络爬虫
# @File :模拟登录QQ邮箱.py
# @IDE :PyCharm
# @Author :艳烔
# @Date :2024/10/31 8:11
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get('https://wx.mail.qq.com/')
login_from_1 = driver.find_element(By.CLASS_NAME, 'QQMailSdkTool_login_loginBox_qq_iframe')
driver.switch_to.frame(login_from_1)
login_from_2 = driver.find_element(By.ID, 'ptlogin_iframe')
driver.switch_to.frame(login_from_2)
# 点击 密码登录 按钮
driver.find_element(By.ID, 'switcher_plogin').click()
# 发送账号密码
driver.find_element(By.ID, 'u').send_keys('5636816663')
driver.find_element(By.ID, 'p').send_keys('123456')
# 点击登录按钮
driver.find_element(By.ID, 'login_button').click()
# 后面需要进行安全验证
time.sleep(3)