day05

本文详细介绍了网页反爬虫的常见策略,包括User-Agent检测、IP封锁、请求频率限制及验证码破解,并提出了相应的解决方案。此外,重点讲解了Selenium库在处理动态内容和模拟浏览器行为中的应用,以及如何安装和使用ChromeDriver和PhantomJS。同时,还阐述了Ajax技术的工作原理,以及如何分析和利用Ajax接口获取数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、反爬策略

面试:必问一个点。----间接反映你的反爬能力。

1、通过user-agent来判断是否是爬虫.

​ 解决办法:封装user-agent。

​ 准备user-agent池

[
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)",
"Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
"Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)",
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)",
"Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)",
"Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)",
"Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)",
"Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6",
"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1",
"Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0",
"Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5",
"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like Gecko) Chrome/19.0.1036.7 Safari/535.20",
"Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52",
]

2、封ip:是网站针对爬虫最终策略。

​ 解决办法:使用代理ip—代理池项目

3、通过请求的频率来限制爬取。

​ 解决办法:

​ (1)设置请求头频率限制。time.sleep(0.1-0.9)

​ (2)减少请求次数:能在列表页获取,就不再详情页。但是要记得保存详情页url。

​ 能一次获取,就多次获取。(ajax请求。limit:50)

4、验证码:破解验证码

5、数据不是直接渲染到html页面中,而是通过js异步获取数据。

​ 解决办法:使用内置浏览器引擎的爬虫(selenium+chrome/phantomjs)

二、selenium

数据不是直接渲染到html页面中,而是通过js异步获取数据,这种网页破解的核心就是执行js代码,执行之后数据就会在页面中显示出来。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tvFKIqRW-1633970219298)(assets/1604716100097.png)]

在开发者工具中Elments元素里面的html页面的内容和请求得到html页面内容有时候是不一样的。

找xpath元素的时候如果按照element标签属性找发现没找到,这时候应该查看请求返回真实响应的页面中到底有没有这个属性。

(一)什么是selenium?

Selenium是一个Web的自动化测试工具,可以控制浏览器自动完成某些操作,但是selenium不带浏览器,selenium相当于一个浏览器的驱动程序。

内置浏览器引擎的爬虫组合:

​ 可视化组合:selenium+chrome

​ 无界面组合:selenium+phantomjs

(二)什么是phantomjs?

PhantomJS是一个基于Webkit的“无界面”(headless)浏览器,它会把网站加载到内存并执行页面上的JavaScript,因为不会展示图形界面,所以运行起来比完整的浏览器要高效。

但是phantomjs好久未更新,现在使用起来容易被网站检测出来,进而屏蔽phantomjs。

(三)安装

1、安装selenium

​ pip install selenium==2.48.0

2、安装chromedriver

(1)下载:

​ [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DpmKrVam-1633970219300)(assets/1604716674924.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KfZyCNZa-1633970219302)(assets/1604716860932.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h79ANigZ-1633970219304)(assets/1604716881702.png)]

将下载好的exe工具:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RGBg0Yjq-1633970219305)(assets/1604717027402.png)]

放到pip工具包下面:D:\python\Scripts—目的:这个包肯定是配置过环境变量。

(2)测试:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U2KhaNOM-1633970219307)(assets/1604717133395.png)]

3、phantomjs安装

(1)下载:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R6oajUMc-1633970219308)(assets/1604717224041.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rPFi3TKD-1633970219310)(assets/1604717233326.png)]

(2)安装:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H2x9jEBg-1633970219312)(assets/1604717254843.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4gjRpMcY-1633970219313)(assets/1604717275350.png)]

将上述exe工具放到和chromedirver相同的位置即可。

(3)测试:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-enpd6DnC-1633970219314)(assets/1604717324671.png)]

(四)selenium的基本操作

文档:selenuim常用方法总结.note
链接:http://note.youdao.com/noteshare?id=0142a95cf23fadbaea95809ccb5674b2&sub=02896A50836E4995997A821419D9A063

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hrracdul-1633970219315)(assets/1604720336384.png)]

#导包
import time

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
#1、创建浏览器
#selnium支持各种主流浏览器
driver = webdriver.Chrome()#创建一个可视化的chrome浏览器
# driver = webdriver.PhantomJS()
# driver = webdriver.Firefox()
# driver = webdriver.Safari()
# driver = webdriver.Ie()
#2、请求url
driver.get('https://www.baidu.com/')
input_lable = driver.find_element_by_id('kw')
print(input_lable)#WebElement对象
#WebElement对象相当于页面中的一个一个标签
#WebElement对象所能完成的操作和标签的功能是一致的。
#input-->输入
input_lable.send_keys('python基础大全')
#btn--按钮---点击 click()
#a----->click()
#普通标签:获取属性
print(input_lable.get_attribute('class'))

#找webelement元素的方法有三个:
#通过id选择
# driver.find_element_by_id()
#通过xpath选择
# driver.find_element_by_xpath()
# driver.find_elements_by_xpath()
#通过css选择器选择
# driver.find_element_by_css_selector()
# driver.find_elements_by_css_selector()

btn_submit = driver.find_element_by_xpath('//*[@id="su"]')
btn_submit.click()
#程序的运行必chrome浏览器页面反映要快很多。
#一定要记住等待是非常重要的。
time.sleep(2)
#完成input内容的清空功能
# input_lable.send_keys(Keys.CONTROL,'a')
# input_lable.send_keys(Keys.CONTROL,'x')
# input_lable.send_keys('流畅的python')
# btn_submit.click()

#最大化
# driver.maximize_window()
# #截屏
# driver.save_screenshot('page.png')

# #退出浏览器
# driver.quit()
# #关闭选项卡
# driver.close()
print(input_lable.location)#{'x': 142, 'y': 17}
print(input_lable.size)#{'x': 142, 'y': 17}

(五)豆瓣图书项目

import time
from lxml import etree
from selenium import webdriver
#定位器
from selenium.webdriver.common.by import By
#条件
from selenium.webdriver.support import expected_conditions as EC
#显示等待的对象
from selenium.webdriver.support.wait import WebDriverWait

def get_content_by_selenium(url):
    '''
    通过selenium获取页面数据
    :param url:
    :return:
    '''
    # #1、创建驱动
    # driver = webdriver.Chrome()
    #2、请求url
    driver.get(url)
    #3、等待---非常重要
    #问题:1秒合不合理?
    #第一种:强制等待
    #缺点:时间不好确定,容易造成程序性能的损耗。
    # time.sleep(1)
    #第二种:隐式等待:等到页面加载完成,不再转圈圈为止。
    #20:最大等待时长
    # driver.implicitly_wait(20)
    #弊端:
    #(1)等待页面所有的静态文件以及js全部加载完成。--可能这些内容比较消耗时间。不能等待页面特定元素出现为止。
    #(2)遇到页面异步加载的,不能使用隐式等待。
    #第三种等待方式:显示等待:可以等待【页面特定元素】满足【特定的条件为止】。
    #找元素的方法可以使用定位器:是一个元组
    #(1)创建一个显示等待对象
    wait = WebDriverWait(driver,20)
    #presence_of_element_located:等到元素出现为止--单个元素
    #presence_of_all_elements_located:多个元素
    result = wait.until(EC.presence_of_all_elements_located((By.XPATH,'//div[@id="root"]/div/div[2]/div/div/div[position()>1]')))
    # print(result)

    #4、获取页面内容
    #page_source:页面加载完所有信息后显示的内容
    html_str = driver.page_source
    return etree.HTML(html_str)


def parse_page(tree):
    '''
    提取页面数据
    :param tree:
    :return:
    '''
    div_list = tree.xpath('//div[@id="root"]/div/div[2]/div/div/div[position()>1]')
    print(div_list)
    for div in div_list:
        # print(div)

        try:
            # 书名
            book_title = div.xpath('.//div[@class="title"]/a/text()')[0]
            book_url = div.xpath('.//div[@class="title"]/a/@href')[0]
            # print(book_title)
            infos = div.xpath('.//div[@class="meta abstract"]/text()')[0].split('/')
            if len(infos)>=4:
                book_author = infos[0]
                book_price = infos[-1]
                book_publish = infos[-3]
                book_pub_date = infos[-2]

                item = {}
                item['book_title'] = book_title
                item['book_url'] = book_url
                item['book_author'] = book_author
                item['book_price'] = book_price
                item['book_publish'] = book_publish
                item['book_pub_date'] = book_pub_date
                print(item)

        except Exception:
            pass
def main():
    #1、确定url
    base_url = 'https://book.douban.com/subject_search?search_text=python&cat=1001&start=%s'
    #2、分页
    # for i in range(30):
    for i in range(5):
        tree = get_content_by_selenium(base_url %(i*15))
        #3提取页面数据
        parse_page(tree)
if __name__ == '__main__':
    # 1、创建驱动--放到全局变量中
    driver = webdriver.Chrome()
    main()

三、ajax

AJAX—异步的 JavaScript 和 XML

AJAX 不是新的编程语言,而是一种使用现有标准的新方法。不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。

AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。

(一)ajax原理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vBduGMqW-1633970219316)(assets/ajax原理.png)]

(二)ajax分析流程

案例:豆瓣电影

第一步:找接口

​ 通过js事件来确定接口。

​ 确定了页面数据变化的事件----滑动。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gFI9fSYW-1633970219317)(assets/1604737986510.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9QWo5KTW-1633970219318)(assets/1604738008804.png)]

第二步:定接口

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j13Zz6CF-1633970219319)(assets/1604738055565.png)]

第三步:分析接口

​ 分析的目标是:不管是post请求还是get请求,参数都是分析的目标

​ 如果参数加密了----变成js加密。—非常难。

​ 一般分析参数方法就是:对比。对比的目的:找到变化参数,这些变化的参数就是分析的重点。

第四步:写代码

​ 思路:先获取参数,在发送ajax请求。

​ 豆瓣电影:

​ (1)从首页获取type值
(2)发送ajax请求。

import json

import requests,re
from lxml import etree
def get_content(url,headers ):
    response = requests.get(url,headers=headers)
    return response.text
def get_type_id(type_urls):
    '''
    获取type_id
    :param type_urls:
    :return:
    '''
    type_ids = []
    #/typerank?type_name=剧情&type=11&interval_id=100:90&action=
    for type_ in type_urls:
        type_id = re.search(r'&type=(.*?)&',type_).group(1)
        # print(type_id)
        type_ids.append(type_id)
    return type_ids

def request_ajax(type_id):
    '''
    发送ajax请求
    :param type_id:
    :return:
    '''
    ajax_url = 'https://movie.douban.com/j/chart/top_list?'
    headers = {
        'X-Requested-With': 'XMLHttpRequest',
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36',
    }


    #for循环做分页一般用在知道循环多少页的情况下
    #while 循环是不知道循环多少页的情况下使用
    i = 0
    while True:

        # 请求参数字典
        params = {
            'type': type_id,
            'interval_id': '100:90',
            'action': '',
            'start': str(i*20),
            'limit': '20',
        }
        resposne = requests.get(ajax_url,headers=headers,params=params)
        #分页结束--到达最后一页
        if resposne.text=='[]':
            break
        #提取数据
        json_data = resposne.json()
        for data in json_data:
            print(data)
        #页码+1
        i+=1

def main():
    #1、获取type值
    base_url  = 'https://movie.douban.com/chart'
    page_content = get_content(base_url,headers=headers)
    # print(page_content)
    tree = etree.HTML(page_content)
    type_urls = tree.xpath('//div[@class="types"]/span/a/@href')
    # print(type_urls)
    type_ids = get_type_id(type_urls)
    #2、请求ajax
    for type_id  in type_ids:
        request_ajax(type_id)

if __name__ == '__main__':
    headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36',
    }
    main()

ge_content)
type_urls = tree.xpath(’//div[@class=“types”]/span/a/@href’)
# print(type_urls)
type_ids = get_type_id(type_urls)
#2、请求ajax
for type_id in type_ids:
request_ajax(type_id)

if name == ‘main’:
headers = {
‘user-agent’: ‘Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36’,
}
main()






作业:斗鱼直播通过ajax获取数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值