Selenium/Xpath/BeautifulSoup

2019-03-04  本文已影响0人  222AblackA

一: selenium库 -- 模拟用户登陆,并解析网页

应用现状:

selenium模拟浏览器进行数据抓取无疑是当下最通用的数据采集方案,它通吃各种数据加载方式,能够绕过客户JS加密,绕过爬虫检测,绕过签名机制。它的应用,使得许多网站的反采集策略形同虚设。由于selenium不会在HTTP请求数据中留下指纹,因此无法被网站直接识别和拦截

selenium在运行的时候会暴露出一些预定义的Javascript变量(特征字符串),例如"window.navigator.webdriver",在非selenium环境下其值为undefined,而在selenium环境下,其值为true

大众点评网的验证码表单页,如果是正常的浏览器操作,能够有效的通过验证,但如果是使用selenium就会被识别,即便验证码输入正确,也会被提示“请求异常,拒绝操作”,无法通过验证

知道了屏蔽的原理,只要能够隐藏这些特征串就可以了。但是还不能直接删除这些属性,因为这样可能会导致selenium不能正常工作了。我们采用曲线救国的方法,使用中间人代理,比如fidder, proxy2.py或者mitmproxy,将JS文件(本例是yoda.*.js这个文件)中的特征字符串给过滤掉(或者替换掉,比如替换成根本不存在的特征串),让它无法正常工作,从而达到让客户端脚本检测不到selenium的效果
(以上内容借用其他作者语录)

安装: pip install selenium

安装浏览器驱动:

查找到与自己装的浏览器先匹配的驱动进行下载
淘宝镜像驱动下载地址:https://npm.taobao.org/mirrors/chromedriver
最好将下载的chromdriver.exe ⽂件放到Python Scripts⽬录下或者配置PATH路径

导入selenium库,生成浏览器对象

可以复制导入以下常用函数

from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver import ActionChains

生成浏览器对象:

brower = webdriver.Chrome()

生成无头浏览器对象:

chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--headless')
brower = webdriver.Chrome(chrome_options=chrome_options)

设置网页窗口大小

browser.set_window_size(1400, 700)

设置最大等待时间

wait = WebDriverWait(browser, 5)

访问网页,生成网页页面对象

browser.get('https://www.mkv99.com/vod-detail-id-9462.html')

selenium相关函数方法:

获取渲染数据后的页面内容
a= browser.page_source

获取当前页面的url
browser.current_url

获取当前页面的cookies
browser.get_cookies()

根据节点的id查找获取节点对象
input1 = browser.find_element_by_id('1thUrlid第01集')

获取节点属性值
href = input1.get_attribute('href'))

css选择器获取节点
input_list = browser.find_elements_by_css_selector('.dwon2')

获取节点在页面中坐标(左上角)
input1.location

获取节点的宽高
input1.size

利用xpath方法获取节点:
input3 = browser.find_element_by_xpath('//*[@class="dwon2"]')
通过name的值获取
input4 = browser.find_element_by_name('CopyAddr1')
a= input4.tag_name
通过文本文字获取有该文字的一个标签
input5 = browser.find_element_by_link_text('今日更新')
通过文本文字获取有该文字的多个标签
input6 = browser.find_elements_by_partial_link_text('下载')
获取节点文本值
input5.text

让页面执行js代码(让页面滑动到底部)
str_js = 'var scrollHeight = document.body.scrollHeight;window.scrollTo(0, scrollHeight);'
browser.execute_script(str_js)


通过css选择器选择节点,并且等到该节点能被点击时获取(在最大等待时间内) --
next_page = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#J_topPage .fp-next')))
通过xpath获取节点,并且等到该节点存在时获取(在最大等待时间内) --
next_page = wait.until(EC.presence_of_element_located((By.XPATH, '//a')))
通过text文本内容获取节点,并且等到该节点存在时获取(在最大等待时间内) --
next_page = wait.until(EC.presence_of_element_located((By.LINK_TEXT, '你好')))
通过标签名获取节点,并且等到该节点存在时获取(在最大等待时间内) --
next_page = wait.until(EC.presence_of_element_located((By.TAG_NAME, 'a')))
            --其他方法参照具体情况调用--


模拟用户点击next_page这个标签节点,其他模拟用户的事件在最下面 -- 
next_page.click()

模拟用户操作浏览器上节点对象的方法 -- (需指定节点对象来调用下列方法)
click(on_element=None) ——单击鼠标左键
click_and_hold(on_element=None) ——点击鼠标左键,不松开
context_click(on_element=None) ——点击鼠标右键
double_click(on_element=None) ——双击鼠标左键
drag_and_drop(source, target) ——拖拽到某个元素然后松开
drag_and_drop_by_offset(source, xoffset, yoffset) ——拖拽到某个坐标然后松开
key_down(value, element=None) ——按下某个键盘上的键
key_up(value, element=None) ——松开某个键
move_by_offset(xoffset, yoffset) ——鼠标从当前位置移动到某个坐标
move_to_element(to_element) --鼠标移动到某个元素
move_to_element_with_offset(to_element, xoffset, yoffset) --移动到距某个元素(左上⾓坐标)多少距离的位置
perform() ——执⾏链中的所有动作
release(on_element=None) ——在某个元素位置松开鼠标左键
send_keys(*keys_to_send) ——发送某个键到当前焦点的元素
send_keys_to_element(element, *keys_to_send) ——发送某个键到指定元素

二: lxml库 (支持HTML和XML解析,xpath解析方式)

xpath是XQuery的一个子集,XQuery是处理xml和html页面的路径查询语言,专用于xml中沿着路径(专业术语叫轴)查找数据用的,可以返回单个元素、文本元素、多个元素节点、属性节点等

1.安装并导入 -- pip install lxml

导入库etree:
from lxml import etree 
将页面数据html转为etree对象:
etree_html = etree.HTML(html)

2.调用xpath方法解析:

匹配对象中所有节点 --> //* 
result = etree_html.xpath('//*') -- 结果是Elenment对象

匹配所有a标签节点 --> //a
result = etree_html.xpath('//a') -- 结果是Elenment对象

获取文本 --> text()
result = etree_html.xpath('//a/text()') -- 结果是元素是文本的列表


查找元素子节点 --> /
result = etree_html.xpath('//div/p/text()')

查找元素class属性匹配的所有子孙节点 --> //
result = etree_html.xpath('//div[@class="channel-item"]')

查找多个节点 --> | (或者的意思)
result = etree_html.xpath('//div[@class="channel-item"] | //span[@class="pubtime"]/../span/a/text()')

查询获取节点的父节点 --> ..
result = etree_html.xpath('//span[@class="pubtime"]/..')

查询或者属性的值 
result = etree_html.xpath('//div[@class="article"]/div/@class')

属性多值匹配(包含)
result = etree_html.xpath('//div[contains(@class, "grid-16-8")]

多属性匹配 --> or, and, mod, //book | //cd, + - * div = != < > <= >=
result = etree_html.xpath('//span[@class="pubtime" and contains(text(), "-12-29")]/text()')

按顺序选择获取节点 -->
 [1] -- 第一个, [last()] -- 最后一个, [position() < 3] -- 前两个, [last() -2] -- 倒数第3个 
result = etree_html.xpath('//div[1]')
result = etree_html.xpath('//div[last()]')


其他按条件匹配获取节点方式:

//li/ancestor::*  li所有祖先节点
//li/ancestor::div div这个祖先节点
//li/attribute::* attribute轴,获取li节点所有属性的值
//li/child::a[@href="link1.html"]  child轴,获取直接子节点
//li/descendant::span 获取所有span类型的子孙节点   
//li/following::* 选取文档中当前节点的结束标记之后的所有节点
//li/following-sibling::*     选取当前节点之后的所有同级节点

三 : BeautifulSoup -- 靓汤

1. 安装 -- pip install beautifulsoup4

导入BeautifulSoup库:
 from bs4 import BeautifulSoup

调用解析器,生成网页数据html的解析对象:
soup = BeautifulSoup(html, 'lxml')

2. beautifulsoup的四种解析器:

Python标准库 -- BeautifulSoup(html, 'html.parser') -- 速度 一般,容错能力好
lxml HTML解析器BeautifulSoup(html, 'lxml') -- 速度快,容错好
lxml xml解析器 BeautifulSoup(markup, 'xml') -- 速度快,唯一支持xml
html5lib 解析器 BeautifulSoup(markup, 'html5lib') -- 容错性高,速度慢

a = soup.prettify() -- 将网页格式化,有缩进的格式整齐输出  (print(a))
title = soup.title.string -- 取网页title的内容
head = soup.head -- 取head标签所有内容(有多个标签,只取第一个)
name = soup.p.name -- 获取标签名

获取标签的某一个属性值 -- 返回字符串
print(soup.img.attrs["src"])
print(soup.img['src'])

获取该标签的所有属性值 -- 返回结果是一个字典
print(soup.img.attrs)

获取p标签中所有标签对象 -- 返回列表,元素是标签的bs对象
a= soup.p.contents

获取的标签对象可以继续选择 
soup.head.title.string

取节点下面所有子节点列表
soup.p.contents


    soup.p.descendants -- 取节点所有子孙节点
    soup.a.parent -- 取父节点
    soup.a.parents --  取所有祖先节点
    soup.a.next_sibling -- 同级下⼀节点
    soup.a.previous_sibling -- 同级上⼀节点
    soup.a.next_siblings -- 同级所有后⾯节点
    soup.a.previous_siblings -- 同级所有前⾯节点
    列子:  list(soup.a.parents)[0].attrs['class'])

方向选择器:

    根据属性和文本查找 -- 
    for ul in soup.find_all(name="ul"):
     print(ul.find_all(name="li"))
     for li in ul.find_all(name="li"):
     print(li.string)
    soup.find_all(attrs={"id": "list-1"})
    
    css选择器:
    soup.select('.panel .panel_heading')
    soup.select('ul li')
    soup.select('#id1 .element')
上一篇下一篇

猜你喜欢

热点阅读