第五章 反爬措施、动态html之selenium

一、反扒策略
1、通过user-agent来判断是不是爬虫

​ 解决的办法:伪装user-agent客户端标识

2、通过访问频率来判断

​ 解决的办法:设置请求频率。time.sleep(random.randint(0,5))

3、封ip

​ 设置代理ip。
​ requests.get(
​ url,
​ headers,
​ params,
​ proxies,代理字典(盛放ip)
​ )
​ proxies={
​ ‘http’:‘http://ip:port’,
​ }

4、页面内容不是直接渲染,而是通过js动态加载获取

​ 解决办法:selenium+phantomjs来解决。

二、html页面技术
1、js

​ html是页面骨架,css是装饰,js是页面的行为。
​ js非常重要。

2、jquery

​ js的库,作用就是简化js编程。

3、ajax

​ web的异步请求技术。
​ 异步请求:
​ 同步请求:

4、Dhtml略
三、selenium和phantomjs
1、什么是selenium

​ selenium是一个web自动化测试工具。但是它本身不带浏览器的功能。他这个工具其实就是可以作为一些外部应用的驱动程序一样,可以控制外部应用来完成一些任务。

2、selenium安装
​	pip install selenium==2.48.0
3、什么是phantomjs

​ phantomjs它其实就是一个内置浏览器无界面浏览器引擎。他可以像浏览器一样加载页面,运行页面中的js代码。

4、为什么selenium和phantomjs的组合可以解决任何网站的页面数据问题

​ selenium就像一个python程序,phantomjs就相当于一个浏览器。他们的结合就相当于用python来控制浏览器进行页面内容的解析,所以,只要能在浏览器中加载的页面,就一定能通过这个组合获取到数据。

5、phantomjs的安装

​ 搜索phantomjs镜像,用镜像下载速度比较快。
​ phantomjs-2.1.1-windows.zip这个包怎么使用:在这个里面找到phantomjs.exe,将这个exe文件放到anaconda的scripts包下面。就可以不用配置环境变量了。
​ 测试是否安装好:在cmd窗口下面输入phantomjs,如果不报错,就说明安装成功。

6.安装可视化chrome浏览器的驱动

​ 下载安装chromedriver.exe---->这驱动就是可以让selenium驱动谷歌一个驱动。---->下载的时候一定要对照自己chrome浏览器的版本。
​ 下载:搜索chromedriver镜像。
​ chromedriver_win32.zip,在里面找到chromedriver.exe,把他也放到anaconda的scripts包下面。

7、selenium的使用
# 1,导入webdriver 
from selenium import webdriver

# 2,创建一个driver对象
driver = webdriver.Phantomjs()
# driver = webdriver.Chrome()  # 使用谷歌浏览器

# 3.请求url
driver.get(url)

#4.等待(强制等待,建议使用显示等待)
time.sleep(2)

# 5.获取页面源码
html_str = driver.page_source
8、下面以爬取豆瓣读书的书籍信息为例,介绍selenium的使用
# 导入需要的模块
from selenium import webdriver
from lxml import etree
import time

#创建driver,使用谷歌浏览器
driver = webdriver.Chrome()

# 爬取网页内容
def get_xpath_by_selenium(url):
    # 1,请求url
    driver.get(url)
    # 2,等待
    time.sleep(3)
    # 3,获取页面源码内容
    html_str = driver.page_source
    # 4,返回页面的element对象
    return etree.HTML(html_str)

# 解析每一页,获取数据信息
def parse_page(html):
    '''
    获取的内容:
        书名,评价数,作者出版社,价格,出版日期,评分,图片链接,详情页链接
    '''
    # selenium获取的页面都是js加载的页面,这种页面都有一个特点:页面虽然都是js代码,但是会放一个空
    # div,将来获取到数据,就是插入到这个div中,所以我们在用xpath找数据的时候,只要从这个div开始定位
    # 就一定能找到。 
    div_list = html.xpath('//div[@id="root"]/div/div[2]/div/div') # 使用xpath 筛选数据范围 
    # print(div_list)
    for div in div_list:
        # 书名
        name = get_text(div.xpath('.//div[@class="title"]/a/text()')) #使用xpath精确查找数据
        # 评价数
        if name:
            comment_num = get_text(div.xpath('.//span[@class="pl"]/text()'))
            infos = get_text(div.xpath('.//div[@class="meta abstract"]/text()'))
            # print(infos)  # [美] 埃里克·马瑟斯 / 袁国忠 / 人民邮电出版社 / 2016-7-1 / 89.00元
            infos = infos.split('/')
            # 作者
            author = infos[0]
            # 出版社
            publish = infos[-3]
            # 价格
            price = infos[-1]
            # 出版日期
            date = infos[-2]
            # 评分
            scores = get_text(div.xpath('.//span[@class="rating_nums"]/text()'))
            # 图片链接
            img_url = get_text(div.xpath('.//div[@class="item-root"]/a/img/@src'))
            # 详情页链接
            detail_url = get_text(div.xpath('.//div[@class="item-root"]/a/@href'))
            item = {}
            item['name'] = name
          	......
            print(item)
            # 保存数据,略
            
# 定义返回数据的方法
def get_text(text):
    if text:
        return text[0]
    return ''

def main():
    base_url = 'https://search.douban.com/book/subject_search?search_text=python&cat=1001&start=%s'
    # 分页,爬取前10页
    for i in range(10):
        html = get_xpath_by_selenium(base_url%(i*15)) # 执行函数方法
        parse_page(html)  # 执行爬取每一页信息的方法

if __name__ == '__main__':
    main()
9、将函数方法改装成类方法,使用显示等待 , 代码如下:
from selenium import webdriver
# 导入显示等待所需要的三个包
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from lxml import etree
import time

class Douban(object):
    def __init__(self,url):
        self.url = url
        self.driver = webdriver.Chrome()
        # 第一个参数,等待作用哪个driver,20为最大等待时长,20s后还没等待数据出来,就报timeout超时异常
        self.wait = WebDriverWait(self.driver,20)
        self.parse()  # 执行爬取方法

    def parse(self):
        # 分页,爬取前10页
        for i in range(10):
            html = self.get_xpath_by_selenium(self.url % (i * 15),'//div[@id="root"]/div/div[2]/div/div')  # 执行函数方法
            self.parse_page(html)

    def get_xpath_by_selenium(self,url,xpath):
        # 1,请求url
        self.driver.get(url)
        # 2,强制等待,不建议使用
        # time.sleep(3)
        # 显示等待:By.XPATH,定位的选择器的名称,元组的第二个参数是定位器,即数据的位置。
        self.wait.until(EC.presence_of_all_elements_located((By.XPATH,xpath)))
        # 3,获取页面内容
        html_str = self.driver.page_source
        # 4,返回页面的element对象
        return etree.HTML(html_str)

    def get_text(self,text):
        if text:
            return text[0]
        return ''

    def parse_page(self,html):
        '''
        获取的内容:
            书名,评价数,作者出版社,价格,出版日期,评分,图片链接,详情页链接
        '''
        div_list = html.xpath('//div[@id="root"]/div/div[2]/div/div')
        # print(div_list)
        for div in div_list:
            # 书名
            name = self.get_text(div.xpath('.//div[@class="title"]/a/text()'))
            # 评价数
            if name:
                comment_num = self.get_text(div.xpath('.//span[@class="pl"]/text()'))
                infos = self.get_text(div.xpath('.//div[@class="meta abstract"]/text()'))
                #print(infos)#[美] 埃里克·马瑟斯 / 袁国忠 / 人民邮电出版社 / 2016-7-1 / 89.00元
                infos = infos.split('/')
                # 作者
                author = infos[0]
                # 出版社
                publish = infos[-3]
                # 价格
                price = infos[-1]
                # 出版日期
                date = infos[-2]
                # 评分
                scores = self.get_text(div.xpath('.//span[@class="rating_nums"]/text()'))
                # 图片链接
                img_url = self.get_text(div.xpath('.//div[@class="item-root"]/a/img/@src'))
                # 详情页链接
                detail_url = self.get_text(div.xpath('.//div[@class="item-root"]/a/@href'))
                item = {}
                item['name'] = name
                .....
                print(item)

if __name__ == '__main__':
    base_url = 'https://search.douban.com/book/subject_search?search_text=python&cat=1001&start=%s'
    Douban(base_url)  # 实例化对象,传入url












  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值