Python-Spider 爬虫基础

2025-03-08 1 0

爬虫的基本流程

  • 基本流程

    • 目标数据:需要什么数据

    • 来源地址

    • 结构分析

      • 具体数据在哪(网站、还是APP)

      • 如何展示的数据

    • 实现构思

    • 编写代码

爬虫的基本手段

  • 破解请求限制

    • 请求头设置,如:useragant为有效客户端

    • 控制请求频率(根据实际情景)

    • IP代理

    • 签名/加密参数从html/cookie/js分析

  • 破解登录授权

    • 请求带上用户cookie信息

  • 破解验证码

    • 简单的验证码可以使用识图读验证码第三方库

解析数据

  • HTML Dom解析

    • 正则匹配,通过的正则表达式来匹配想要爬取的数据,如:有些数据不是在html 标签里,而是在html的script 标签的js变量中

    • 使用第三方库解析html dom,比较喜欢类jquery的库

  • 数据字符串

    • 正则匹配(根据情景使用)

    • 转 JSON/XML 对象进行解析

简单爬取页面数据

from urllib.request import urlopen

url = 'http://www.baidu.com'
resp = urlopen(url)
print(resp.read().decode()[:100])

urllib

  • requset.urlopen(url,data,timeout)

    • 第一个参数url即为URL,是必须要传送的。第二个参数data是访问URL时要传送的数据,第三个timeout是设置超时时间。

    • 第二三个参数是可以不传送的,data默认为空None,timeout默认为`socket._GLOBAL_DEFAULT_TIMEOUT

  • response.read()

    • read()方法就是读取文件里的全部内容,返回bytes类型

  • response.getcode()

    • 返回 HTTP的响应码,成功返回200,4服务器页面出错,5服务器问题

  • response.geturl()

    • 返回 返回实际数据的实际URL,防止重定向问题

  • response.info()

    • 返回 服务器响应的HTTP报头

获取响应信息

代码 含义
resp.json() 获取响应内容(以json字符串)
resp.text 获取响应内容 (以字符串)
resp.content 获取响应内容(以字节的方式)
resp.encoding 获取网页编码
resp.headers 获取响应头内容
resp.request.headers 请求头内容
resp.url 获取访问地址
resp.cookie 获取cookie

request对象

使用urllib.request.urlopen发送请求时,可以将参数封装到一个Request对象中。
参数包含:

  • url 发送的请求链接

  • headers 请求头信息

  • data 请求数据

请求头

名称 含义
Accept 告诉服务器,客户端支持的数据类型
Accept-Charset 告诉服务器,客户端采用的编码
Accept-Encoding 告诉服务器,客户机支持的数据压缩格式
Accept-Language 告诉服务器,客户机的语言环境
Host 客户机通过这个头告诉服务器,想访问的主机名
If-Modified-Since 客户机通过这个头告诉服务器,资源的缓存时间
Referer 客户机通过这个头告诉服务器,它是从哪个资源来访问服务器的。(一般用于防盗链)
User-Agent 客户机通过这个头告诉服务器,客户机的软件环境
Cookie 客户机通过这个头告诉服务器,可以向服务器带数据
Refresh 服务器通过这个头,告诉浏览器隔多长时间刷新一次
Content-Type 服务器通过这个头,回送数据的类型
Content-Language 服务器通过这个头,告诉服务器的语言环境
Server 服务器通过这个头,告诉浏览器服务器的类型
Content-Encoding 服务器通过这个头,告诉浏览器数据采用的压缩格式
Content-Length 服务器通过这个头,告诉浏览器回送数据的长度

基本请求

HTTP的基本请求

  • get

  • post

  • put

  • delete

  • head

  • options

GET请求

大部分被传输到浏览器的html,images,js,css, … 都是通过GET方法发出请求的。它是获取数据的主要方法
Get请求的参数都是在Url中体现的,如果有中文,需要转码,这时我们可使用

  • urllib.parse.urlencode() 转换键值对

  • urllib.parse. quote() 转换一个值

POST请求

POST请求的参数需要放到Request请求对象中,data是一个字典,里面要匹配键值对

# 当data为字典,要转换为bytes类型
from urllib.parse import urlencode
_data = {}
data = urlencode(_data).encode

post发送表单数据和json数据皆可

import requests

url = url

# from表单数据
from_data = {
    "name": "micdy",
    "book": "test"
}

req = requests.post(url, data=from_data)
print(req.text)

# json数据
json_data = {
    "name": "micdy",
    "book": "test"
}

req = requests.post(url, json=json_data)
print(req.text)

Cookie

urlib使用cookie

使用cookie保持登录,为了保持Cookie不丢失可以urllib.request.HTTPCookieProcessor来扩展opener的功能

handler = HTTPCookieProcessor()
opener = build_opener(handler)

保存cookie
可以利用本模块的http.cookiejar.CookieJar类的对象来捕获cookie并在后续连接请求时重新发送,比如可以实现模拟登录功能。该模块主要的对象有CookieJar、FileCookieJar、MozillaCookieJar、LWPCookieJar

cookie_jar = MozillaCookieJar()
handler = HTTPCookieProcessor(cookie_jar)
cookie_jar.save('cookie.txt',ignore_discard=True,ignore_expires=True)

使用保存的cookie

cookie_jar.load('cookie.txt',ignore_discard=True,ignore_expires=True)
handler = HTTPCookieProcessor(cookie_jar)
opener = build_opener(handler)

requests使用cookie

使用Session方法启用会话

s = requests.Session()
print(s.cookies)

'''
-> Cookie session=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZG1pbiIsImV4cCI6MTczNzYxOTMxNn0.EbyLG-885Ng3sAIr7NNxZS0NnufKSe6jm76rzVAa7r8
'''

requests.Session()会创建一个会话对象,这个对象会在多次请求间自动管理 cookie。当你使用这个会话对象发送请求时,服务器返回的 Set - Cookie头信息会被会话对象自动保存。在后续使用该会话对象发送的请求中,会话对象会自动在请求头里添加保存的 cookie,从而保持会话状态。

  • 创建会话对象:s = requests.Session()创建了一个 Session对象 s

  • 登录请求:login_resp = s.post(url, data=form_data)发送登录请求,服务器返回的 cookie会被 s自动保存。

  • 后续请求:info_resp = s.get(url)发送后续请求时,s会自动在请求头中添加之前保存的 cookie,以此保持会话状态。

import requests

def login():
    url = "http://localhost:8000/playground/login"
    data = {
        "uname": "admin",
        "password": "123456"
    }
    s = requests.Session()
    login_resp = s.post(url, data=data)

    url = "http://localhost:8000/playground/user_info"
    login_resp = s.get(url)
    print(login_resp.text)
  
if __name__ == "__main__":
    login()

Token

Token是服务器生成的一串字符串,作为客户端在后续请求时的身份标识和授权依据。客户端成功登录或完成特定操作后,服务器会创建一个Token并返回给客户端,之后客户端每次向服务器发送请求时都需要携带这个Token,服务器通过验证Token的有效性来确认客户端的身份和权限。
服务器接收到登录信息后,对用户的身份进行验证,若验证通过,服务器会根据用户的相关信息(如用户 ID、角色等)生成一个Token。

Token具有时效性。

Token通常由三部分组成

  • 头部(Header):包含Token的类型(如JWT)和使用的签名算法(如 HMAC SHA256、RSA 等),并进行Base64Url编码。

  • 载荷(payload):包含声明(Claims),声明是关于实体(通常是用户)和其他数据的声明,可分为注册声明(如iss发行人、sub主题、aud受众等)、公开声明和私有声明。同样进行 Base64Url 编码。

  • 签名(Signature):为了创建签名部分,需要使用编码后的头部、编码后的载荷、一个秘钥(只有服务器知道),使用头部中指定的签名算法进行签名,以确保Token未被篡改。

服务器将生成的Token返回给客户端,客户端通常会将Token存储在本地,如浏览器的本地存储(Local Storage)或会话存储(Session Storage)中,也可以存储在Cookie里。
后续的请求中,可以在Authorization字段携带Token,服务器会对Token进行验证,

利用Token登录

import requests

url = "http://localhost:8000/playground/login2"
data = {
    "uname": "admin",
    "password": "123456"
}
resp = requests.post(url, json=data)
token = resp.json().get("access_token")
login_url = "http://localhost:8000/playground/user_info2"

headers = {
    "Authorization": f"Bearer {token}"
}
resp = requests.get(login_url, headers=headers)
print(resp.json())

使用场景

  • 身份验证:用于验证用户的身份,确保只有经过授权的用户才能访问受保护的资源。例如,用户登录电商网站后,服务器生成 Token,用户在浏览个人订单、修改个人信息等操作时都需要携带该 Token 进行身份验证。

  • 授权:可以根据 Token 中包含的用户角色和权限信息,决定用户可以执行哪些操作。比如,管理员用户的 Token 可能包含更高的权限,允许其进行用户管理、商品上架等操作,而普通用户的 Token 权限则相对较低。

  • 单点登录(SSO):在多个相关的 Web 应用中,用户只需在一个应用中登录,服务器生成的 Token 可以在其他关联应用中使用,实现一次登录,多处访问。

urllib底层

当你获取一个URL你使用一个opener(一个urllib.OpenerDirector的实例)。在前面,我们都是使用的默认的opener,也就是urlopen。它是一个特殊的opener,可以理解成opener的一个特殊实例,传入的参数仅仅是url,data,timeout
如果我们需要用到Cookie,只用这个opener是不能达到目的的,所以我们需要创建更一般的opener来实现对Cookie的设置

网页页面

  • 静态页面:访问有UI页面URL,可以直接获取数据

  • 动态页面(AJAX):访问有UI页面URL,不能获取数据。需要抓取新的请求获取数据

有些网页内容使用AJAX加载,而AJAX一般返回的是JSON,直接对AJAX地址进行post或get,就能返回JSON数据了。在xhr,异步请求中寻找。

SSL证书

如果SSL证书验证不通过,或者操作系统不信任服务器的安全证书,会警告用户证书不受信任。
忽略ssl的安全性

import ssl
context = ssl._creat_unverified_context()
response = urlopen(request,context = context)

伪装爬虫请求

有些网站不会同意程序直接用上面的方式进行访问,如果识别有问题,那么站点根本不会响应。

fake-useragent

pip install fake-useragent

fake-useragent在创建对象时,可能创建不了,多部分原因为服务器访问不到的原因
可以拷贝fake-useragent_version.json的配置文件到用户目录

from fake_useragent import UserAgent

ua = UserAgent()

print(ua.chrome)
print(ua.firefox)
print(ua.edge)
Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Mobile Safari/537.36
Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:123.0) Gecko/20100101 Firefox/123.0
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36 Edg/121.0.0.0

代理ip

代理分类

  • 透明代理:目标网站知道你使用了代理并且知道你的源IP地址,这种代理显然不符合我们这里使用代理的初衷

  • 匿名代理:匿名程度比较低,也就是网站知道你使用了代理,但是并不知道你的源IP地址

  • 高匿代理:这是最保险的方式,目标网站既不知道你使用的代理更不知道你的源IP

代理网站

代理网站目前可用,但不一定稳定。毕竟这个产业目前情况就是这样。

构建hander实现

hander = ProxyHandler({'http': 'ip:port'})
opener = build_opener(hander)

4A评测 - 免责申明

本站提供的一切软件、教程和内容信息仅限用于学习和研究目的。

不得将上述内容用于商业或者非法用途,否则一切后果请用户自负。

本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑或手机中彻底删除上述内容。

如果您喜欢该程序,请支持正版,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。敬请谅解!

程序来源网络,不确保不包含木马病毒等危险内容,请在确保安全的情况下或使用虚拟机使用。

侵权违规投诉邮箱:4ablog168#gmail.com(#换成@)

相关文章

[Meachines] [Easy] Luanne Lua RCE+bozoHTTPd LFI+NetBSD-Dec+doas权限提升
[Meachines] [Easy] Toolbox PostgreSQLI-RCE+Docker逃逸boot2docker权限提升
[Meachines] [Easy] ServMon NVMS-LFI+NSCP(NSClient)权限提升+Chameleon反向shell+reg…
塔塔科技遭勒索攻击,1.4TB数据被泄露
GitHub官方展示如何利用Copilot进行日志安全分析
通过物理渗透测试获取内部网络访问权限:案例分析

发布评论