动态内容的获取
-
JavaScript逆向 —> 找到真正提供数据的API接口 —> Response —> json()
- 浏览器开发者工具 —> Network —> XHR(JavaScript获得数据的异步请求)
- 专业抓包工具 —> Fiddler / Charles / Wireshark
-
直接操控浏览器 —> selenium —> WebDriver
- pip install selenium —> from selenium import webdriver
- 把下载好的chromedriver放到虚拟环境下的Scripts(bin)目录下 —> PATH
- browser = webdriver.Chrome()
这个图片里描述了如何去获取元素的一些方法,可以根据这些方法得到我们所需要的元素
异步编程
异步编程(异步I/O)- 实现了协作式并发,大幅度的提升了CPU利用率
被async修饰的函数异步函数,调用异步函数不是直接得到返回值,而是创建一个协程对象(可以跟其他子程序相互协作的子程序)
async def display(num):
print(num)
await asyncio.sleep(1)
# 调用异步函数得到的是一个协程对象
cos_list = [display(n) for n in range(1, 11)]
# 启动一个事件循环,将协程对象注册到事件循环上(注册之后才能协作)
loop = asyncio.get_event_loop()
# 将列表中的协程对象处理成一个Task对象然后挂到事件循环上
# 相当于将10个协程对象都注册到事件循环上
loop.run_until_complete(asyncio.wait(cos_list))
loop.close()
通过selenium登录qq空间
- 在对qq空间的登录表单点击右键检查后发现,这个表单是在一个内嵌的窗口中,所以我们需要先切换到页面内嵌的窗口(iframe)中
- 然后在iframe中查找超链接、用户名、密码和登录按钮
- 最后直接用代码操控登录就可以了
from selenium import webdriver
import getpass
driver = webdriver.Chrome()
driver.get('https://qzone.qq.com/')
# 先切换到页面内嵌的窗口(iframe)中
iframe = driver.find_element_by_id('login_frame')
driver.switch_to.frame(iframe)
# 在iframe中去查找超链接、用户名、密码和登录按钮
anchor = driver.find_element_by_id('switcher_plogin')
anchor.click()
username_input = driver.find_element_by_id('u')
username = input('Username: ')
username_input.send_keys(username)
password_input = driver.find_element_by_id('p')
password = getpass.getpass()
password_input.send_keys(password)
login_button = driver.find_element_by_id('login_button')
login_button.click()
注意:在上面代码中需要输入自己的用户名和密码,如果直接在控制台输入,会让自己的密码显露出来,所以我们用了getpass三方库中的getpass()方法,然后在终端运行代码就可以在输入密码的时候不显示密码
了解JavaScript
- 语法规范:ECMAScript(ES)
- window(把浏览器窗口封装成一个对象):BOM(Browser Object Model)
- document:DOM(Document Object Model)
window
- 属性
- navigator
- history
- location
- screen
- document(!重点)
- 方法
- alert() / prompt() / confirm()
- open() / close()
- setTimeout() / setInterval()
JavaScript核心语法
-
数据类型:
- number - 整数
- string - 字符串(单引号或者双引号)
- boolean - true/ false
- null - 空类型
- undefined - 未定义
- symbol - 符号类型
- object - 对象类型
-
变量
- var
- let(建议使用下面这个)
var定义全局变量
ES6中新增了let命令,用来声明局部变量,但是所声明的变量,只在let命令所在的代码块内有效,这样可以让我们更安全的使用和写代码
- 规范:
- 变量必须以字母开头
- 变量也能以$和_符号开头(但是不建议使用)
- 变量名称对大小写敏感
- 多个单词从采取驼峰式命名
-
JavaScript可以通过不同的方式来输出数据
- windo.alert() - 弹出警告框
- document.write() - 将内容写道HTML文档中
- innerHTML - 写入到HTML元素
- console.log() - 写入到浏览器的控制台
-
条件语句
- if 语句
- if else
- if else if else
- switch
-
for 循环 - 可以将代码块执行指定的次数
for (语句1;语句2) {
执行代码块
}
let total = 0
// 两个分号分隔三个部分,分别是:
// let i = 1 ---> 初始条件(进入循环的时候只执行一次)
// i <= 100 ---> 循环控制条件(条件成立就会执行循环体)
// ++i ---> 步进条件(相当于循环体中的最后一条语句,每循环一次就要执行)
for (let i = 1; i <= 100; ++i) {
total += i
}
-
while 循环 - 在指定条件为true时循环执行代码块
while (条件) {
执行的代码块
}
let total = 0
let i = 1
while (i <= 100) {
total += i
i += 1
}
-
do/while 循环 - 因为代码块会在条件被测试前执行,所以该循环至少会执行一次
do {
执行的代码块
}
while (条件)
let total = 0
do {
total += i
i += 1
} while (i <= 100)
-
条件运算符
(condition)? value1 : value2
满足条件,返回value1,否则返回value2
猜数字游戏
let answer = parseInt(Math.random() * 100 + 1)
let counter = 0
let yourAnswer = 0
do {
yourAnswer = window.prompt('请输入你猜的数字: ')
if (yourAnswer > answer) {
window.alert('小一点')
} else if (yourAnswer < answer) {
window.alert('大一点')
} else {
window.alert('恭喜你猜对了')
}
} while( answer != yourAnswer)
if (counter > 7) {
window.alert('温馨提示: 智商捉急!!!')
}
以上写了一段猜数字的游戏,可以娱乐娱乐
乘法口诀表
document.write('<table>')
for (let col = 1; col <= 9; ++col) {
document.write('<tr>')
for (let row = 1; row <= col; ++row){
document.write(`<td>${row}×${col}=${col*row}</td>`)
}
document.write('</tr>')
}
document.write('</table>')
数组
-
作用:使用单独的变量名来存储一系列的值
-
方法:
-
let fruits = new Array()
fruits[0] = ‘Apple’
fruits[1] = ‘Orange’
fruits[2] = ‘Banana’
-
let fruits = new Array(‘Apple’, ‘Orange’, ‘Banana’)
-
let fruits = [‘Apple’, ‘Orange’, ‘Banana’]
建议使用第三种方法
-
-
常用操作
-
遍历数组
fruits.forEach(function(x, index) {
console.log(x, index)
})
-
push() - 将项目添加到数组的末尾
-
pop() - 从数组末尾删除项目
-
unshift() - 将项目添加到数组的开头
-
shift() - 从数组的开头删除一项
-
indexOf() - 从数组中找到项目的索引
-
Array[index] - 使用索引位置访问数组项
-
splice(index, n) - 从索引位置删除项目,n代表删除几个
-
splice(index, n, item) - 从索引位置删除项目后并添加项目
-
length - Array.length - 返回数组元素的个数
-
sort() - 对数组的元素进行排序
默认排序顺序为按字母升序,**注意:使用数字排序,会将25’排在’45’的前面,必须通过函数作为一个参数来调用
numbers.sort(function compareNumbers(a, b) {
return a - b
})
也可以使用箭头函数表达式
numbers.sort((a, b ) => a-b)
该函数将按升序对数组进行排序
-
双色球
// 从1-33的号码中选出6个红色球, 从1-16的号码中选出1个蓝色球,
// 红色球和蓝色球放到一起构成一组号码 ---> 随机选号
let redBalls = []
for (let i = 1; i <= 33; ++i) {
redBalls.push(i)
}
let selectedBalls = []
for (let i = 0; i < 6; ++i) {
let index = parseInt(Math.random() * redBalls.length)
selectedBalls.push(redBalls[index])
redBalls.splice(index, 1)
}
selectedBalls.sort((a, b) => a - b)
selectedBalls.forEach((ball) => {
document.write('<div class="red">' + (ball < 10? '0' : '') + ball + '</div>')
})
blueBall = parseInt(Math.random() * 16 + 1)
selectedBalls.push(blueBall)
document.write('<div class="blue">' + (blueBall < 10? '0' : '') + blueBall + '</div>')
.red, .blue{
width: 120px;
height: 120px;
color: white;
float: left;
border-radius: 60px;
text-align:center;
font: bold 64px/120px 'Courier New', Courier, monospace;
margin-left: 20px;
margin-top: 320px;
}
.red {
background-color: red;
}
.blue {
background-color: blue;
}
面向对象编程
- 对象定义:在JavaScript中,几乎所有事物都是对象
- 对象属性:对象中的命名值,被称为属性
- 对象方法:方法是可以在对象上执行的动作,对象方法是包含函数定义的对象属性
- 关键词:this - 被称为this的事物,指的是拥有该javaScript代码的对象
JavaScript HTML DOM
通过HTML DOM,JavaScript能够访问和改变HTML文档的所有元素
-
HTML DOM - 当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model)
HTML DOM模型被结构化为对象树;
- 方法:
- 查找HTML元素
- document.getElementById(id) —> HTMLElement
- getElementsByClassName(name) —> NodeList[HTMLElement]
- getElementsByTagName(name) —> NodeList[HTMLElement]
- documeng.querySelector(’…’) —> HTMLElement
- document.querySelectorAll(’…’) —> NodeList[HTMLElement]
- 改变HTML元素
- element.innerHTML = new html content
- element.textContent = new content
- element.attribute = new value
- element.setAttribute(attribute, value)
- element.style.property = new style
- 添加和删除元素
- document.creatElement(element)
- document.removeElement(element)
- document.appendChild(element)
- document.insertBefore(element)
- document.replaceChild(element)
- document.write(text)
- 查找HTML元素
延迟跳转
h1><span id="num">5</span>秒钟以后自动跳转到百度</h1>
function getRandomColor() {
let red = parseInt(Math.random() * 256)
let green = parseInt(Math.random() * 256)
let blue = parseInt(Math.random() * 256)
return `rgb(${red}, ${green}, ${blue})`
}
let numSpan = document.querySelector('#num')
let counter = 5
setInterval(() => {
counter -= 1
// 通过HTMLElement对象的textcontent属性修改标签内容
numSpan.textContent = counter
// 通过HTMLElement对象的style属性修改标签样式
numSpan.style.color = getRandomColor()
if (counter == 0) {
location.href = "https://www.baidu.com"
}
}, 1000)
-
事件监听器
- addEventListener() - 为指定元素指定事件处理程序,为元素附加事件处理程序而不会覆盖已有的事件处理程序
- 语法:element.addEventListener(event, function, useCapture)
- event - 事件的类型
- function - 当事件发生时我们需要调用的函数
- useCapture - 布尔值,指定使用事件冒泡还是事件捕获,这个参数可选
-
DOM 节点
- HTML文档中的所有事物都是节点
- 整个文档是文档节点
- 每个HTML元素是元素节点
- HTML元素内的文本是文本节点
- 每个HTML属性是属性节点
- 所有注释都是注释节点
- 节点关系
-
父、子和同胞,parent、child以及sibling描述这些关系
-
同胞指定是拥有相同父的节点
-
- 节点导航
- 访问父节点:parentNode
- 访问子节点:children / firstElementChild / lastElementChild
- 访问兄弟节点:previousElementSibling / nextElementSibling
- HTML文档中的所有事物都是节点
动态
#container {
width: 800px;
height: 400px;
border: 1px solid black;
margin: 10px auto; /* 上、右、下、左 */
overflow: hidden;
}
#container+p {
width: 800px;
margin: 10px auto;
text-align: center;
}
#container+p>button {
width: 80px;
height: 30px;
border: none;
outline: none;
background-color: darkcyan;
color: white;
font-size: 18px/30px;
}
.square {
width: 80px;
height: 80px;
float: left;
}
<div id="container"></div>
<p>
<button id="add">添加</button>
<button id="flash">闪烁</button>
</p>
// 下面是JS代码
function getRandomColor() {
let red = parseInt(Math.random() * 256)
let green = parseInt(Math.random() * 256)
let blue = parseInt(Math.random() * 256)
return `rgb(${red}, ${green}, ${blue})`
}
let addButton = document.querySelector('#add')
let containerDiv = document.querySelector('#container')
addButton.addEventListener('click', () => {
// 创建新的元素(标签)
let newDiv = document.createElement('div')
// 修改标签的class属性指定类名
newDiv.className = 'square'
// 修改标签的style属性定制背景色
newDiv.style.backgroundColor = getRandomColor()
// 将新创建的div标签插入到父标签的第一个子标签前(最前面)
containerDiv.insertBefore(newDiv, containerDiv.firstChild)
})
let flashButton = document.querySelector('#flash')
let timerId = 0
// 事件监听器中传入的函数的参数是一个事件对象(封装了和发生的事件相关的所有信息)
flashButton.addEventListener('click', (evt) => {
if (timerId === 0) {
// 启动计时器(setInterval方法会返回计时器的ID)
timerId = setInterval(() => {
let allDivs = document.querySelectorAll('#container>div')
allDivs.forEach((div) => {
div.style.backgroundColor = getRandomColor()
})
}, 200)
// 通过事件对象的target属性获取事件源(引发事件的标签)
evt.target.textContent = '暂停'
} else {
// 清除计时器
clearInterval(timerId)
timerId = 0
evt.target.textContent = '闪烁'
}
})
动态列表
在Python和JavaScript中,函数是一等函数(一等公民)
- 函数可以赋值给变量
- 函数可以作为函数的参数
- 函数可以返回函数
* {
margin: 0;
padding: 0;
}
body {
background-color: #000;
color: #fff;
}
#app {
width: 40%;
margin: 20px auto;
}
#fruits>li {
width: 90%;
height: 50px;
background-color: #6ca;
margin: 4px 0;
text-align: center;
font-size: 20px;
list-style-type: none;
line-height: 50px;
}
#fruits>li>a {
float: right;
color: #fff;
text-decoration: none;
margin-right: 10px;
}
#fruits+div {
margin-top: 20px;
}
input[type=text] {
width: 70%;
height: 40px;
color: #fff;
border-radius: 8px;
border: none;
outline: none;
font-size: 20px;
text-align: center;
vertical-align: middle;
background-color: #999;
}
#ok {
width: 19%;
height: 40px;
color: #fff;
background-color: #a45;
border: none;
outline: none;
font-size: 16px;
vertical-align: middle;
}
<div id="app">
<ul id="fruits">
<li>苹果<a href="">×</a></li>
<li>香蕉<a href="">×</a></li>
<li>榴莲<a href="">×</a></li>
<li>火龙果<a href="">×</a></li>
</ul>
<div>
<input type="text" id="fname">
<button id="ok">确定</button>
</div>
</div>
<script>
let removeLi = (evt) => {
// 通过事件对象的preventDefault方法阻止事件的默认行为
evt.preventDefault()
// 获得事件源(被点击的a标签)的父节点
let li = evt.target.parentNode
// 通过父节点删除子节点
li.parentNode.removeChild(li)
}
let addItem = (evt) => {
let content = input.value.trim()
if (content.length > 0 ) {
let newLi = document.createElement('li')
newLi.textContent = content
let anchor = document.createElement('a')
anchor.href = ''
anchor.textContent = '×'
anchor.addEventListener('click', removeLi)
newLi.appendChild(anchor)
ul.appendChild(newLi)
}
// 清空文本框的输入并使其获得焦点
input.value = ''
input.focus() // 失去焦点: blur()
}
let anchors = document.querySelectorAll('#fruits>li>a')
anchors.forEach((anchor) => {
anchor.addEventListener('click', removeLi)
})
let ul = document.querySelector('#fruits')
let okButton = document.querySelector('#ok')
let input = okButton.previousElementSibling
input.addEventListener('keypress', (evt) => {
if (evt.keyCode === 13) {
addItem(evt)
}
})
okButton.addEventListener('click', addItem)
</script>
</body>
fetch API
用fetch来获取数据,如果响应正常返回,会返回一个response对象,我们可以调用方法得到我们需要的格式的数据,比如:JSON、TEXT等
通过API接口加载数据
* {
margin: 0;
padding: 0;
}
body {
background-color: #000;
color: #fff;
}
#app {
width: 80%;
margin: 20px auto;
text-align: center;
}
#news>li {
width: 90%;
height: 50px;
background-color: #6ca;
margin: 4px 0;
text-align: center;
font-size: 20px;
list-style-type: none;
line-height: 50px;
}
#news>li>a {
color: white;
text-decoration: none;
}
#news+div {
width: 90%;
margin-top: 20px;
text-align: center;
}
#ok {
width: 100%;
height: 40px;
color: #fff;
background-color: #a45;
border: none;
outline: none;
font-size: 22px;
}
<body>
<div id="app">
<ul id="news"></ul>
<div>
<button id="ok">加载</button>
</div>
</div>
<script>
let ul = document.querySelector('#news')
let okButton = document.querySelector('#ok')
okButton.addEventListener('click', (evt) => {
// 使用fetch联网通过API接口获取JSON格式的数据
fetch('http://api.tianapi.com/guonei/index? key=4d5d18219d3be64947c5f59e755fb3d1&num=10')
.then(resp => resp.json())
.then(json => {
// 将获取到的JSON格式的数据动态的添加到页面上(把数据渲染到页面上)
json.newslist.forEach((news) => {
let newItem = document.createElement('li')
let anchor = document.createElement('a')
anchor.href = news.url
anchor.target = '_blank'
anchor.textContent = news.title
newItem.appendChild(anchor)
ul.appendChild(newItem)
})
})
})
</script>
</body>
ECharts
通过引入ECharts可以绘制我们需要的图表
#main {
width: 600px;
height: 400px;
}
<div id="main"></div>
<script src="https://cdn.bootcdn.net/ajax/libs/echarts/4.8.0/echarts.min.js"></script>
<script>
// 将div初始化为一个绘图的区域(准备画布)
let myChart = echarts.init(document.querySelector('#main'))
// option对象定义了图表上使用的数据
let option = {
title: {
text: 'ECharts 入门示例'
},
tooltip: {},
legend: {
data:['上半年', '下半年']
},
xAxis: {
data: ["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"]
},
yAxis: {},
series: [
{
name: '上半年',
type: 'bar',
data: [15, 20, 36, 10, 10, 20]
},
{
name: '下半年',
type: 'bar',
data: [35, 12, 26, 20, 18, 25]
}
]
}
// 使用刚指定的配置项和数据渲染图表
myChart.setOption(option)
</script>