爬虫_基础知识

一,一些基本的内容

# 什么是爬虫?

爬虫就是模拟客户端(浏览器)发送网络请求,获取响应,按照一定的规则提取数据,模拟客户端发(浏览器)送网络请求:发送和浏览器一模一样的数据,获取和浏览器一模一样的请求

# 爬虫的数据去哪了
呈现出来:展示在网页上,展示在app上
就行分析:对爬取的数据进行分析

# HTTP:超文本传输协议
以明文方式进行传输
效率高,但是安全性低

# HTTPS:HTTP+SSL(安全套接字层)
传输之前先进行加密,之后再进行解密获取内容
效率较低,但是安全

# HTTP协议之请求
1:请求行
2:请求头
User-Agent:用户代理,对方的服务器能通过User-Agent直到当前请求对方服务器的资源的是什么浏览器
Cookie:用来存储用户的部分信息,每次请求时会携带Cookie发送给对方的服务器
3:请求体
用于携带数据
GET请求没有请求体
POST请求有请求体

# HTTP协议之响应
1:响应头
Set-Cookie:对方通过该字段设置Cookie到本地
2:响应体
url地址对应的响应

# 使用超时参数

requests.get(url,headers = headers,timeout=3)    # 该请求再3秒内必须返回响应,否则会报错
二,retrying模块
raise会抛出异常(自定义异常)
# 如果出现错误就会一直重试
@retry
def func():
    print("...")
    
# stop_max_attempt_number 最带的重试次数
@retry(stop_max_attempt_number = 5)
def func():
    print("ERROR")
    raise

# stop_max_delay 失败重试最大事件,单位为毫秒,超出时间立即停止重试
@retry(stop_max_delay=1000)
def func():
    print("重试执行该方法的时间为1秒,超过1秒则不继续执行")
    raise
    
# wait_fixed 设置失败重试的时间间隔
@retry(wait_fixed = 1000)
def func():
    print("该方法会一直重试,其每次重试的时间隔为秒")
    raise

# wait_random_min, wait_random_max 设置失败重试随机性间隔时间
@retry(wait_random_min=1000, wait_random_max=3000)
def func():
    print("每次失败是重试的时间间隔为随机性的,且该随机数再1秒和3秒之间")

# wait_exponential_multiplier-间隔时间倍数增加,wait_exponential_max-最大间隔时间

@retry(wait_exponential_multiplier=1000, wait_exponential_max=10000)
def func():
    print "Wait 2^x * 1000 milliseconds between each retry, up to 10 seconds, then 10 seconds afterwards"
    print int(time.time())
    raise
三,requests 模块的使用
 # requests中的参数
1
method # 请求方式,常见的请求方式有GET/POST 2 url # 将要获取的页面的url链接 3 param # 可以利用 字典/字符串/字节作为url的参数 4 data # 可以利用 字典/字符串/字节/文件最为Request请求携带的数据 5 json # 用以json为格式的数据,用来作为Request的内容 6 headers # 以字典的形式,请求中携带的一些请求头如user-agent,来模拟浏览器的访问 7 cookies # 用来存储用户的部分信息,用来进行下一次访问携带的数据 8 files # 传输文件 9 auth # 权限,以元组形式,支持HTTP认证的功能 10 timeout # 超时参数,可设置最长链接时间,或设置连接时间和内容读取时间(元组形式) 11 allow_redirects # 是否允许重定向 12 proxies # 字典类型,可设置代理服务器 13 verify # 自动进行网站证书的认证,默认为True 14 stream # 是否将获取的内容立即下载,默认为True

# request中参数的解释

# method
def param_method():
    requests.request(method = "get")
    requests.request(method = "post")

# url
def param_url():
    requests.request(
        method = "get",
        url = "https://www.baidu.com"
    )

# data
def param_data():
    # data可以是字典的形式
    requests.request(
        method = 'post',
        url = "https://www.baidu.com",
        data = {"k1":"v1","k2":"v2"}
    )
    
    # data可以是字符串的形式
    requests.request(
        method = 'post',
        url = "https://www.baidu.com",
        data = "k1=v1; k2=v2;"
    )

    # data可以是以字节的形式
    # 待补充
    
    # data可以是以文件的形式
    requests.request(
        method = 'post',
        url = "https://www.baidu.com",
        data = open('test.py', mode='r', encoding='utf-8'), 
        # 文件内容是:k1=v1;k2=v2
    )

# json
def param_json():
    # 将json中对应的数据进行序列化成一个字符串,json.dumps(...)
    # 然后发送到服务器端的body中,并且Content-Type是 {'Content-Type': 'application/json'}
    post_dict = {
        "BaseRequest": {
            "DeviceID": "e155674455601272",
            "Sid": TICKET_DICT["wxsid"],
            "Skey": TICKET_DICT["skey"],
            "Uin": TICKET_DICT["wxuin"],
        },
        "SyncKey":USER_INIT_DICT["SyncKey"],
        "rr":1
    }
    requests.request(
        method = 'POST',
        url = "https://www.baidu.com"
        json = post_dict
    )

# headers
def param_headers():
    headers =     {
        "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36",
        "Host":"www.baidu.com"
        }
    requests.request(
        method = "GET",
        url = "https://www.baidu.com",
        headers = headers
    )

# cookies
def param_cookies():
    cookie = "...sug=3; sugstore=0; ORIGIN=0;..."
        requests.request(
        method = "GET",
        url = "https://www.baidu.com",
        cookies = cookie
    )

# files 文件上传
def param_file():
    requests.post(
        url="https://www.baidu.com",
        file={"files":open("images.jpg"."rb")}
    )

# 遇到需要认证的网站 可以使用requests中的auth实现
from requests.auth import HTTPBasicAuth, HTTPDigestAuth
ret = requests.request(
    method = "get",
    url = 'https://www.baidu.com',
    auth=HTTPBasicAuth('user', '123'))
        
# timeout 超时参数    
requests.get(url,headers = headers,timeout=3)    # 该请求再3秒内必须返回响应,否则会报错

# timeout元组类型(发送时间/读取时间)
ret = requests.get(url, timeout=(5, 1))
    
# 是否允许重定向
ret = requests.get('https://www.baidu.com', allow_redirects=False)    

# proxies 代理(向代理服务器发送请求,代理服务器再向url发送请求)
response = requests.get(
    url = url,
     proxies = {
          "http": "http://127.0.0.1:9743",        # 代理服务器IP地址
          "https": "https://127.0.0.1:9743",
        }
    )        

# stream 流 当请求时不立即获取结果,可通过迭代的方式来获取结果
如果为false会将所有文件一下子下载下来
如果为true会一点一点的下载文件(内存不足情况下使用)
def param_stream():
    ret = requests.get('https://www.baidu.com', stream=True)
    print(ret.content)
    ret.close()

    # 迭代
    from contextlib import closing
    with closing(requests.get('https://www.baidu.com', stream=True)) as r:
    # 在此处理响应。
    for i in r.iter_content():
    print(i)

# 证书
response = requests.get(
    url = url,
    cert="test.pem",    # 主动提供证书文件,证书文件引入方式
    verify=False        # 忽略网站证书的存在,照样能返回结果
)    
四,BeautifulSoup 模块的使用

 BeautifulSoup是做什么用的?

BeautifulSoup是一个模块,该模块用于接收一个HTML或XML字符串,然后将其进行格式化,之后遍可以使用他提供的方法进行快速查找指定元素,从而使得在HTML或XML中查找指定元素变得简单。

from bs4 import BeautifulSoup

html_list = """
<html>
    <head>
        <title>BeautifulSoup</title>
    </head>
<body>
    <div class="title">
        <b>这是title中的b标签中的文本</b>
        <h1>这是title中h1标签中的文本</h1>
    </div>
<div class="story">
    <p>友情链接</p>
    <a href="https://www.baidu.com" class="link" id="link2">百度首页</a>
    <a href="https://fanyi.baidu.com/" class="link" id="link3">百度翻译</a>
</div>
</body>
</html>
"""
# # 利用BeautifulSoup将html对象转成BeautifulSoup对象soup
# # features="html.parser" 为本次处理的引擎
soup = BeautifulSoup(html_list,features="html.parser")

# 利用find来获取第一个匹配的标签
tag = soup.find("a")
tag = soup.find(name="a",attrs={"class":"link"},test="百度首页")    # 中可有多个参数,必须都匹配才能被选中

# 获取所有匹配的标签
tag = soup.find_all("a")
tag = soup.find_all(name="a",attrs={"class":"link"},test="百度首页")
#
# 找到第一个a标签
tag_a1 = soup.find(name = "a")

# 找到所有的a标签
tag_a_all = soup.find_all(name = "a")

# 找到id为link2的标签
tag_id = soup.select("#link2")

# 找到class为link的标签
tag_class = soup.select(".link")

## name 标签名称操作
tag = soup.find("a")
name = tag.name         # 获取当前标签的名称
tag.name = "p"          # 修改标签的名称
print(soup)

## 标签属性操作
tag1 = soup.find("a")
attrs = tag1.attrs          # 获取属性的值 href class id 的值
tag1.attrs["id"] = "newid"  # 将id的值修改为newid
del attrs["class"]          # 将class属性删除
print(attrs)

## 获取所有的子标签
body = soup.find("body")
c = body.children           # 获取body中所有的子标签
print(list(c))

## 获取所有子子孙孙标签
body1 = soup.find("body")
d = body1.descendants
print(list(d))

## 将所有的子标签清空
tag = soup.find("body")
tag.clear()         # 留下<body></body>
print(soup)

## 利用递归删除所有的标签,并获取被删除的标签
test = soup.find("body")
e = test.extract()      # 将body标签也删除
print(soup)
print(e)                # e 的值包括所有被删除的标签及其其中的内容

# 将对象转为字符串
test = soup.find("body")
d = test.decode()           # 获取标签及其标签中的内容,也就是包括body标签
d2 = test.decode_contents() # 只获取标签中的内容,也就是步包括body标签
print(d2)

# 将对象转为字节
test = soup.find("body")
e = test.encode()           # 包含当前的标签
e2 = test.encode_contents() # 不含当前的标签
print(e2)

## 找到所有的a和p标签
t = soup.find_all(name=["a","p"])

## 找到id = "link"  或者 id="link2",class也是如此
t = soup.find_all(id = ["link","link2"])

## 找到文本文件
t = soup.find_all(text="百度首页")

# get, 获取标签属性
tag = soup.find('a')
v = tag.get('id')
print(v)

# has_attr, 检查标签是否具有该属性
tag = soup.find('a')
v = tag.has_attr('id')
print(v)

# get_text, 获取标签内部文本内容
tag = soup.find('a')
v = tag.get_text()
print(v)

# index, 检查标签在某标签中的索引位置
tag = soup.find('body')
v = tag.index(tag.find('div'))
print(v)

tag = soup.find('body')
for i,v in enumerate(tag):
    print(i,v)

# is_empty_element,是否是空标签(是否可以是空)或者自闭合标签,
# 判断是否是如下标签:'br' , 'hr', 'input', 'img', 'meta','spacer', 'link', 'frame', 'base'
tag = soup.find('br')
v = tag.is_empty_element
print(v)

## 获取标签中的内容
tag = soup.find("p")
print(tag.string)                  # 获取标签中的内容
tag.string = "修改原有的内容"      # 设置内容
print(tag.string)
tag = soup.find("body")
a = tag.stripped_strings            # 获取标签内部所有的文本信息,提取所有的文本内容
print(list(a))

## 追加标签
tag = soup.find("body")
tag.append(soup.find("a"))      # 取得a标签,将其追加到body中,将原本存在的a标签删除(相当于移动)
print(soup)

## 创建一个标签,并将其追加到body的末尾
from bs4.element import Tag
obj = Tag(name='i',attrs={'id': 'idvalue'})
obj.string = '我是标签中的文本内容'
tag = soup.find('body')
tag.append(obj)
print(soup)

## 在当前标签内部指定位置插入一个标签
from bs4.element import Tag
obj = Tag(name='i', attrs={'id':'idvalue'})
obj.string = '我是标签中的文本内容'
tag = soup.find('body')
tag.insert(1, obj)      # 为1表示再body中的第一个位置插入该标签,为2表示再body中第一个子标签后插入该标签
print(soup)

## insert_after,insert_before 在当前标签后面或前面插入
from bs4.element import Tag
obj = Tag(name='i', attrs={'id': 'idvalue'})
obj.string = '我是标签中的文本内容'
tag = soup.find('body')
tag.insert_before(obj)            # 在当前标签的前面插入(例如body之前)
# tag.insert_after(obj)           # 在当前标签的后面插入
print(soup)

## 将当前标签替换为指定标签(会将原本标签删除,再加入该标签)
from bs4.element import Tag
obj = Tag(name='i', attrs={'id': 'idvalue'})
obj.string = '我是标签中的文本内容'
tag = soup.find('div')
tag.replace_with(obj)
print(soup)

## 创建标签之间的关系
tag = soup.find('div')
a = soup.find('a')
tag.setup(previous_sibling=a)
print(tag.previous_sibling)

## wrap,将指定标签把当前标签包裹起来
from bs4.element import Tag
obj1 = Tag(name='div', attrs={'id': 'it'})
obj1.string = '我是一个新来的'
tag = soup.find('a')
v = tag.wrap(obj1)      # a标签将被新创建的div标签包裹起来
print(soup)

## 去掉当前标签,将保留其包裹的标签,该标签的子标签也会保留,该标签的文本内容也会被保留
tag = soup.find('a')
v = tag.unwrap()        # 将第一个a标签去掉 保留其包裹的标签
print(soup)

# BeautifulSoup中的css选择器

# 选择二所有的title标签
soup.select("title")
# 选择所有p标签中的第三个标签 soup.select("p:nth-of-type(3)")

# 选择body下的 a 标签 soup.select("body a")

# 选择html下的head下的title标签 soup.select("html head title") soup.select("span,a")

# 选择head标签下的直接title标签 soup.select("head > title")

# 选择p节点下id=link1的直接子节点 soup.select("p > #link1")

# 选择body下的所有a直接节点 soup.select("body > a")

# 选择id为link1后的class=sisiter的所有兄弟节点 soup.select("#link1 ~ .sister")

# 选择id为link1后的class=sisiter的第一个兄弟节点 soup.select("#link1 + .sister")

# 选择class=sisiter的所有节点 soup.select(".sister")

# 选择class=sisiter的所有节点 soup.select("[class="sister]")

# id为link1的节点 soup.select("#link1")

# 选择a节点,且a节点的id为link2 soup.select("a#link2")

# 选择所有的a节点,且a节点含有属性href soup.select('a[href]')

# 指定href属性值的a节点 soup.select('a[href="http://example.com/elsie"]')

# 指定href属性以指定值开头的a节点 soup.select('a[href^="http://example.com/"]')

# 指定href属性以指定结尾的所有a节点 soup.select('a[href$="tillie"]')

# 利用正则表达式进行匹配 soup.select('a[href*=".com/el"]')

待补充...

猜你喜欢

转载自www.cnblogs.com/Doaoao/p/10425921.html