动态页面获取

一、反爬与反反爬

反爬措施(服务器)

  • 通过客户端请求头字段来判断是不是爬虫。
  • 通过在url中拼接加密字段,一般通过js动态生成。
  • 通过判断一个IP在一个时间段内访问频率。
  • 验证码。
  • 不直接在页面中显示数据,通过js进行数据渲染。

反反爬措施(你)

  • 封装常用请求头,列如:user-agent,Referer。
  • 通过 js逆向,或在页面中获得加密字段,。
  • 使用IP池,设置爬取策略
  • 验证码识别
    • 字母验证码,可以通过打码平台识别/自己识别,再输入。
    • 滑动/点击验证码,可通过打码平台识别位置后,通过selenium模拟人工滑动/点击,进行验证。
  • js渲染可通过以下方法获取数据
    • 有些网站数据放置在js代码中,例如36kr。
    • 通过selenium+phantomjs(无界面浏览器)、selenium+chrome来获取数据
    • 找到数据来源的接口(ajax接口)
    • splash获取数据。Splash是一个javascript渲染服务。。
二、ajax
1、什么是ajax

​ Ajax 不是一种新的编程语言,而是一种用于创建更好更快以及交互性更强的Web应用程序的技术。
使用 JavaScript 向服务器提出请求并处理响应而不阻塞用户核心对象XMLHttpRequest。通过这个对象,您的 JavaScript 可在不重载页面的情况与 Web 服务器交换数据,即在不需要刷新页面的情况下,就可以产生局部刷新的效果。Ajax 在浏览器与 Web 服务器之间使用异步数据传输(HTTP 请求),这样就可使网页从服务器请求少量的信息,而不是整个页面。Ajax可使因特网应用程序更小、更快,更友好。

总结下来:ajax是通过XMLHttpRequest对象,在不刷新页面的情况下异步发送请求,接受响应,的一种网络技术。

三、selenium与浏览器驱动安装。
1、安装 selenium 模块
pip install selenium
2、下载浏览器驱动并且安装。

下载 chromedrive,首先需要查看自己的浏览器版本

chromedrive下载地址:https://chromedriver.storage.googleapis.com/index.html?path=80.0.3987.106/

phantomjs下载地址:https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-windows.zip

下载完成后解压,移动到python.exe所在的目录,你也可以进行单独环境变量配置,不过这种方法是最简单的

是否成功,在cmd命令行中输入相关命令

四、selenium简单使用
4.1、常用方法如下
from selenium import webdriver

chrome = webdriver.Chrome()

# 访问url
chrome.get('https://www.baidu.com')

# 元素选择
input_1 = chrome.find_element_by_id('kw')  # 通过id选择
input_2 = chrome.find_element_by_xpath("//input[@id='su']")  # 通过xpath
input_3 = chrome.find_element_by_css_selector('#su')  # 通过css选择器
input_4 = chrome.find_element_by_class_name('bg s_btn')  # 通过类名

# 往输入框内发送内容,并且点击
input_1.send_keys('spider')
button = chrome.find_element_by_xpath('//input[@id="su"]')

# 获取某对象的png bytes数据
content_bytes = button.screenshot_as_png

# 获取元素的位置
print(button.location)
button.click()

# 全屏截图
chrome.save_screenshot('1.png')

# 元素大小
print(button.size)
chrome.close()

# 关闭选项卡
chrome.close()

# 退出浏览器
chrome.quit()

4.2、selenium提取cookies字典
from selenium import webdriver

chrome = webdriver.Chrome()
chrome.get('http://www.baidu.com')

cookies = chrome.get_cookies()

cok_dic = {i.get('name'): i.get('value') for i in cookies}
print(cok_dic)

chrome.close()
chrome.quit()
4.3、selenium中的三种等待

代码执行的速度是非常快的,但是我们通过selenium+浏览器驱动去驱动一个浏览器执行某些动作,但是浏览器执行的速度很慢。我们进行数据提取时,浏览器页面并没有加载完毕,我们可能会提取不到数据,所以需要设置等待。

强制等待:shitime.sleep(1) #程序暂停1秒
隐式等待:chrome.implicitly_wait(5) #最多等待5秒,在5秒内,加载完成就不会报错。
显示等待:指定时间情况下,指定某些元素或者状态是否加载完成。加载完成就不会报错。
from selenium.webdriver.common.by import By #通过什么方式判断:id、xpath、cssselect、等
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
next_page = WebDriverWait(self.browser, 5).until(
                EC.presence_of_element_located((By.XPATH, '//div[contains(@class,"paginator")]/a[last()]'))) #等待a标签是否加载成功。
            next_url = next_page.get_attribute('href')
            
#EC这个类中提供了很多判断条件,下面是常用判断条件
title_is    #title标签内容是..
title_contains #title标签包含。
presence_of_element_located  #元素加载完成
visibility_of_element_located  #元素可视
text_to_be_present_in_element #元素内的内容加载完成
element_to_be_clickable  #元素可点击
element_to_be_selected  #元素可选择

五、相关案例

5.1、豆瓣图书
from selenium import webdriver
import time
import random
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from lxml import etree
import xlwt


class Douband():
    def __init__(self, kw, page):
        self.base_url = 'https://book.douban.com/'
        self.browser = webdriver.Chrome()
        self.page_url = ''
        self.kw = kw
        self.page = page
        self.cont_list = []

    def get_index(self, url):
        self.browser.get(url)
        try:
            next_page = WebDriverWait(self.browser, 5).until(
                EC.presence_of_element_located((By.XPATH, '//div[contains(@class,"paginator")]/a[last()]')))
            next_url = next_page.get_attribute('href')
            self.page_url = next_url
            return self.browser.page_source
        except Exception:
            self.browser.quit()

    def parser_index(self, content):
        html = etree.HTML(content)
        item_list = html.xpath('//div[contains(@class,"sc-bZQynM" )]')
        for item in item_list:
            title = item.xpath('.//div[@class="detail"]/div[@class="title"]/a/text()')
            rating = item.xpath('.//div[@class="detail"]/div[contains(@class,"rating")]/span[2]/text()')
            times = item.xpath('.//div[@class="detail"]/div[contains(@class,"rating")]/span[3]/text()'),
            info = item.xpath('.//div[@class="detail"]/div[@class="meta abstract"]/text()'),
            item = {
                'title': title[0] if title else None,
                'rating': rating[0] if rating else None,
                'times': times[0] if times else None,
                'info': info[0] if info else None,
            }
            print(item)
            self.cont_list.append(item)

    def search(self):
        self.browser.get(self.base_url)
        self.browser.find_element_by_id('inp-query').send_keys(self.kw)
        time.sleep(random.random())
        self.browser.find_element_by_xpath('//div[@class="inp-btn"]/input').click()

    def write_to_excel(self, filename, sheetname):
        # 创建workbook
        file = xlwt.Workbook()

        # 添加sheet表
        sheet = file.add_sheet(sheetname)

        # 设置表头
        head = [i for i in self.cont_list[0].keys()]
        for i in range(len(head)):
            sheet.write(0, i, head[i])
        # 写内容
        i = 1
        for item in self.cont_list:
            for j in range(len(head)):
                sheet.write(i, j, item[head[j]])
            i += 1
        # 保存
        file.save(filename)
        print('写入excle成功!')

    def run(self):
        self.search()
        count = 0
        self.page_url = self.browser.current_url
        while count < self.page:
            content = self.get_index(self.page_url)
            self.parser_index(content)
            count += 1
        self.browser.quit()
        self.write_to_excel('python.xls', 'book')


if __name__ == '__main__':
    db = Douband('python', 10)
    db.run()
5.2、腾讯招聘
import requests
from jsonpath import jsonpath
from excle_wirte import ExcelUtils
import os


def get_content(url):
    headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36',
        'referer': 'https://careers.tencent.com/search.html'
    }

    res = requests.get(url, headers=headers).json()
    jp = jsonpath(res, '$.*.Posts.*')
    print(jp)
    return jp


def write_excel(filename, item_list, sheetname):
    if not os.path.exists(filename):
        ExcelUtils.write_to_excel(filename, item_list, sheetname)
    else:
        ExcelUtils.append_to_excel(filename, item_list)


if __name__ == '__main__':
    base_url = 'https://careers.tencent.com/tencentcareer/api/post/Query?timestamp=1585401795646&countryId=&cityId=&bgIds=&productId=&categoryId=&parentCategoryId=&attrId=&keyword=&pageIndex={}&pageSize=20&language=zh-cn&area=cn'
    for i in range(1, 11):
        content = get_content(base_url.format(i))
        write_excel('tencent.xls',content,'hr')
在这里用到了写入excel的一些方法,我这里直接引用了别人封装的方法。
import xlwt
import xlrd
from xlutils.copy import copy as C


class ExcelUtils(object):
    @staticmethod
    def write_to_excel(filename, item_list, sheetname):
        try:
            # 创建workbook
            workbook = xlwt.Workbook(encoding='utf-8')
            # 给工作表添加sheet表单
            sheet = workbook.add_sheet(sheetname)
            # 设置表头
            head = []
            for i in item_list[0].keys():
                head.append(i)
            # print(head)
            # 将表头写入excel
            for i in range(len(head)):
                sheet.write(0, i, head[i])
            # 写内容
            i = 1
            for item in item_list:
                for j in range(len(head)):
                    sheet.write(i, j, item[head[j]])
                i += 1
            # 保存
            workbook.save(filename)
            print('写入excle成功!')
        except Exception as e:
            print(e)
            print('写入失败!')

    @staticmethod
    def append_to_excel(filename, item_list):
        # 打开excle文件
        work_book = xlrd.open_workbook(filename)
        # 获取工作表中的所有sheet表单名称
        sheets = work_book.sheet_names()
        # 获取第一个表单
        work_sheet = work_book.sheet_by_name(sheets[0])
        # 获取已经写入的行数
        old_rows = work_sheet.nrows
        # 获取表头的所有字段
        keys = work_sheet.row_values(0)
        # 将xlrd对象转化成xlwt,为了写入
        new_work_book = C(work_book)
        # 获取表单来添加数据
        new_sheet = new_work_book.get_sheet(0)
        i = old_rows
        for item in item_list:
            for j in range(len(keys)):
                new_sheet.write(i, j, item[keys[j]])
            i += 1

        new_work_book.save(filename)
        print('追加成功!')
原文地址:https://www.cnblogs.com/hjnzs/p/12596120.html