Python10 ---- 前端基础与爬虫
前端基础与爬虫
一个请求的组成
def request_jd(keyword):
url = "https://search.jd.com/Search"
params = {
"keyword": keyword
}
headers = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36"
}
response = requests.get(url=url, params=params, headers=headers)
response.text 获取str类型的响应内容
response.content 获取bytes类型的响应内容
response.json() 获取json格式数据
-
请求行(request line)
- URL
- 请求方法(method)
-
请求头(headers)
-
user-agent
用来指示当前请求时从哪个终端发起的 -
cookie
用来指示当前的用户信息和行为信息
-
-
请求体(body)
-
params
(严格来说不算是请求体)
实际请求的时候会变成URL的一部分, 所以说post请求也可以用params
- urlencode和urldecode
请求头中指定的编码格式只对请求体是有效的, 不对params有效. 所以urlencode来保证URL不会发生编码问题.from urllib.parse import quote, unquote print(quote("鼠标")) print(unquote("%E9%BC%A0%E6%A0%87"))
- urlencode和urldecode
-
data
携带额外的请求信息.
-
静态页面和动态页面
-
静态页面
纯粹的HTML文件, 简单地说当前的页面文件就存储在服务端, 我们请求的静态页面实际上就是请求对方服务器中的文件. 通过返回不同的HTML文件来完成不同请求的显示效果.- 动态页面和静态页面的区分绝不是指页面上的动画效果
最见的就是各大企业网站
-
动态页面
动态页面是指除了HTML以外, 通过ajax
在不直接刷新页面的前提下, 完成了和服务端的数据交互. 并通过javascript
回调函数完成对页面内容的修改,ajax
和服务端交互的数据格式通常为json
浏览商品
视频网站的瀑布流
-
Ajax
asynchronous JavaScript-XML 异步javascript和xml的缩写
在不直接刷新页面的前提下, 完成了和服务端的数据交互. 并通过
javascript
回调函数完成对页面内容的修改,ajax
和服务端交互的数据格式通常为json
. -
json
js对象标记法, 用来表示对象关系js中的对象: {a: 1, b: null}
- json的作用
是一种跨平台跨语言的传输对象格式, 可以保留一些基础的数据类型信息.原来json只是作为前端和服务端传输数据的格式规范, 但是现在几乎所有热门语言都内置了json, 所以可以称之为跨语言的传输格式
import json test_dict = { "a": 1, "b": ["1", 2, None], "c": {"d": 1} } # json格式数据其实是个字符串 # 将python字典转变为json数据格式 json_data = json.dumps(test_dict) print(type(json_data), json_data) # 将json数据格式转变为字典 print(json.loads(json_data))
- json的作用
-
HTML, CSS和JS
html和js决定了显示的内容, css决定了怎么显示.
-
HTML(HyperTextMarkup Language 超文本标记语言)
- HTML的作用
定义网页的内容的含义和结构.-
tag(标签)
<标签名>
-
<html>
表示当前是一个HTML文档对象 -
<head>
提供一些基础信息# 通过meta标签来表示当前页面的编码格式 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-
<body>
纯内容
-
-
element(元素)
<标签名> xxxxxxxxxx</标签名>
-
- HTML的作用
-
CSS(Cascading Style Sheets 层叠样式表)
能对网页中的元素位置的排版进行像素级别的控制. 页面的渲染主要就是通过
css
来完成的. -
JavaScript
通过<script></script>
包裹, 主要完成数据的交互和对DOM树(HTML是一个结构化的数据文件, DOM就是将结构化的数据转变成对象)的修改.
浏览器渲染的过程
- 接收到HTML文件后开始构建DOM(Doucment Object Model)树.
- CSS来计算DOM树各个节点的坐标, 大小等CSS属性, 开始布局.
- 开始加载媒体资源和页面渲染.
课后作业
- 完成京东搜索页面的请求并保存为HTML格式文件(10个即可, 请求频繁容易被封)
f = open("search_keyword.html", "w", encoding="utf-8")
- 完成京东详情页面的请求并保存为HTML格式文件(10个即可, 请求频繁容易被封)
import requests
# 请求头中指定的编码格式只对请求体是有效的, 不对params有效. 所以urlencode来保证URL不会发生编码问题.
def request_jd(keyword):
url = "https://search.jd.com/Search"
params = {
"keyword": keyword
}
# 请求头
headers = {
# 指客户端使用什么软件访问,或发起的
# cookice 用户或设备的身份信息,仅有真实的身份才会有cookice
"user-agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36"
}
# 请求体 params严格说不属于请求体,而data是,可以携带额外的请求信息.
response = requests.get(url=url, params=params, headers=headers)
# response.text # 获取str类型的响应内容
# response.content #获取bytes类型的响应内容 #有乱码可调试
# response.json() # 获取json格式数据
result = response.text
# print(result)
file_name = keyword
with open(f'search_keyword_{file_name}.html', "w", encoding="utf-8") as f:
f.write(result + "\n")
if __name__ == '__main__':
task_array = ["鼠标", "键盘", "显卡", "耳机"]
for i in task_array:
request_jd(i)
# request_jd('鼠标')
- 练习python中json库的使用
import json
test_dict = {
"a": 1,
"b": ["1", 2, None],
"c": {"d": 1}
}
# json格式数据其实是个字符串
# 将python字典转变为json数据格式
json_data = json.dumps(test_dict)
print(type(json_data), json_data)
# 将json数据格式转变为字典
print(json.loads(json_data))
css-selector
尽量避免解析路径中包含位置信息
chrome页面中内置了Jquery环境, 用$符号来表示
-
直接定位元素
-
通过id进行定位
$("#id值")
-
通过class进行定位
$(".class值")
-
通过属性名进行定位
$("标签名[属性名='属性值']") $("ul[class='gl-warp clearfix']")
-
-
获取兄弟节点
-
获取当前节点的下一个节点
-
dom提供的接口, 不属于css-selector语法
tmp = $("li[data-sku='6039832']")[0] tmp.nextElementSibling
-
通过css-selector(不建议)
$("ul[class='gl-warp clearfix'] li:first-child + li")
-
-
获取当前节点的上一个节点
- dom提供的接口, 不属于css-selector语法
tmp = $("li[data-sku='2136538']")[0] tmp.previousElementSibling
- dom提供的接口, 不属于css-selector语法
-
-
获取父子节点
-
获取父节点
-
dom提供的接口, 不属于css-selector语法
tmp.parentElement
-
-
获取子节点
-
获取所有子节点
-
遍历所有符合条件的元素
$("ul[class='gl-warp clearfix'] div[class='gl-i-wrap']")
-
dom提供的接口, 不属于css-selector语法
$("ul[class='gl-warp clearfix']")[0].children
-
-
获取第一个子节点
:fist-child $("ul[class='gl-warp clearfix'] li:first-child")[0]
-
获取最后一个子节点
:last-child $("ul[class='gl-warp clearfix'] li:last-child")[0]
-
获取第N个子节点
:nth-child(索引) $("ul[class='gl-warp clearfix'] li:nth-child(5)")[0]
-
-
-
模糊匹配
-
匹配开头
^
# 匹配data-sku属性值为2开头的元素 $("li[data-sku^='2']")
-
匹配结尾
$
$("li[data-sku$='2']")
-
匹配子集
*
$("li[data-sku*='2']")
-
-
获取文本值
$("li[data-sku='6039832'] div[class='p-name p-name-type-2'] em")[0].innerText
-
获取属性值
$("ul[class='gl-warp clearfix'] li")[0].getAttribute("data-sku")
BeautifulSoup
-
安装
pip install bs4 pip install lxml
-
使用BeautifulSoup
from bs4 import BeautifulSoup def jd_search_parse(html): soup = BeautifulSoup(html, "lxml") item = soup.select("li[data-sku='6039832']")[0]
-
直接定位元素
略,因select已经满足当前定位的需求了 -
去除空白字符
html = html.replace('\r\n', "").replace("\n", "").replace("\t", "")
-
获取兄弟节点
-
获取上一个节点
tmp_ele.previous_sibling
-
获取下一个节点
tmp_ele.next_sibling
-
-
获取父子节点
-
获取父节点
tmp_ele.parent
-
获取子节点
tmp_ele.children
-
-
模糊匹配
略
-
获取文本值
content = tmp_ele.text.strip()
-
获取属性值
value = tmp_ele.attrs["data-sku"]
课后作业
- 练习css-selector
- 练习用beautifulsoup进行页面解析
一个小又全的爬虫项目
-
任务生成者
生成爬虫任务的组件, 最大的作用就是建立生产消费者模型, 将生产者和消费者剥离, 可以达到程序暂停重启的功能. -
配置文件
当前爬虫项目的基础配置信息, 目的就是统一化配置, 避免重复修改. -
主函数/调度器
以逻辑控制流协同各个组件, 完成爬取工作, 具有一定的调度功能 -
下载器
用来和目标服务器进行交互, 获取数据的组件 -
解析器
用来解析非结构化的页面内容, 获取想要的数据. -
存储器
用来持久化解析后的数据- 数据库
- 存为本地文件, 比较推荐的格式为json, 结构严谨的可以保存为csv
课后作业
- 搭建第一个爬虫项目
- 为当前爬虫项目添加代理
- 扩展: 将当前项目改造成多线程
- 扩展2: 将当前项目改造成多进程
- 扩展3: 通过aiohttp, aiomysql将项目改造成协程.