Django爬虫基本原理及Request和Response分析

一、爬虫

互联网是由网络设备(网线,路由器,交换机,防火墙等等)和一台台计算机连接而成,像一张网一样。

互联网的核心价值在于数据的共享/传递:数据是存放于一台台计算机上的,而将计算机互联到一起的目的就是为了能够方便彼此之间的数据共享/传递,否则就只能拿U盘去拷贝数据了。

互联网中最有价值的便是数据,爬虫模拟浏览器发送请求->下载网页代码->只提取有用的数据->存放于数据库或文件中,就得到了我们需要的数据了

爬虫是一种向网站发起请求,获取资源后分析并提取有用数据的程序。


二、爬虫流程

1、基本流程介绍

发送请求-----> 获取响应内容----->解析内容 ----->保存数据

#1、发起请求
使用http库向目标站点发起请求,即发送一个Request
Request包含:请求头、请求体等

#2、获取响应内容
如果服务器能正常响应,则会得到一个Response
Response包含:html,json,图片,视频等

#3、解析内容
解析html数据:正则表达式,第三方解析库如Beautifulsoup,pyquery等
解析json数据:json模块
解析二进制数据:以b的方式写入文件

#4、保存数据
数据库
文件


2、Request

常用的请求方式:GET,POST

其他请求方式:HEAD,PUT,DELETE,OPTHONS


>>> import requests
>>> r = requests.get('https://api.github.com/events')
>>> r = requests.post('http://httpbin.org/post', data = {'key':'value'})
>>> r = requests.put('http://httpbin.org/put', data = {'key':'value'})
>>> r = requests.delete('http://httpbin.org/delete')
>>> r = requests.head('http://httpbin.org/get')
>>> r = requests.options('http://httpbin.org/get')


百度搜索内容爬取页面:

import requests
response=requests.get("https://www.baidu.com/s",
                      params={"wd":"美女","a":1},
                      headers={
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36"
                      })                #模拟在百度搜索美女的第一页内容,wd后面跟输入的搜索内容  #自己定制headers,解决网站的反爬虫功能
print(response.status_code)
print(response.text)
with open("bd.html","w",encoding="utf8") as f:
    f.write(response.text)                        #下载的页面写进bd.html文件,文件用浏览器打开发现和百度页面一样


3、Response

# 1、响应状态

200:代表成功

301:代表跳转

404:文件不存在

403:权限

502:服务器错误


# 2、Respone header

Location:跳转

set - cookie:可能有多个,是来告诉浏览器,把cookie保存下来


# 3、preview就是网页源代码

最主要的部分,包含了请求资源的内容

如网页html,图片,二进制数据等


# 4、response属性

import requests
respone=requests.get('http://www.jianshu.com')
# respone属性
print(respone.text)                     # 获取响应文本
print(respone.content)                 #获取网页上的二进制图片、视频
print(respone.status_code)               #响应状态码
print(respone.headers)                   #响应头

print(respone.cookies)                   #获取cookies信息
print(respone.cookies.get_dict())
print(respone.cookies.items())

print(respone.url)
print(respone.history)                 #获取history信息(页面经过重定向等方式,不是一次返回的页面)
print(respone.encoding)                #响应字符编码

#关闭:response.close()
from contextlib import closing
with closing(requests.get('xxx',stream=True)) as response:
    for line in response.iter_content():
    pass


#5、获取大文件

#stream参数:一点一点的取,对于特别大的资源,一下子写到文件中是不合理的
import requests
response=requests.get('https://gss3.baidu.com/6LZ0ej3k1Qd3ote6lo7D0j9wehsv/tieba-smallvideo-transcode/1767502_56ec685f9c7ec542eeaf6eac93a65dc7_6fe25cd1347c_3.mp4',
                      stream=True)
with open('b.mp4','wb') as f:
    for line in response.iter_content():           # 获取二进制流(iter_content)
        f.write(line)


三、爬取校花网视频(加了并发的)

import requests         #安装模块 pip3 install requests
import re
import hashlib
import time
from concurrent.futures import ThreadPoolExecutor

pool=ThreadPoolExecutor(50)
movie_path=r'C:\mp4'

def get_page(url):
    try:
        response=requests.get(url)
        if response.status_code == 200:
            return response.text
    except Exception:
        pass
        
def parse_index(index_page):
    index_page=index_page.result()
    urls=re.findall('class="items".*?href="(.*?)"',index_page,re.S)       #找到所有属性类为items的标签的链接地址,re.S表示前面的.*?代表所有字符
    for detail_url in urls:
        ret = re.search('<video.*?source src="(?P<path>.*?)"', res.text, re.S)   #找到所有video标签的链接地址
        detail_url = ret.group("path")
        res = requests.get(detail_url)
        if not detail_url.startswith('http'):
            detail_url='http://www.xiaohuar.com'+detail_url
        pool.submit(get_page,detail_url).add_done_callback(parse_detail)
        
def parse_detail(detail_page):
    detail_page=detail_page.result()
    l=re.findall('id="media".*?src="(.*?)"',detail_page,re.S)
    if l:
        movie_url=l[0]
        if movie_url.endswith('mp4'):
            pool.submit(get_movie,movie_url)
            
def get_movie(url):
    try:
        response=requests.get(url)
        if response.status_code == 200:
            m=hashlib.md5()
            m.update(str(time.time()).encode('utf-8'))
            m.update(url.encode('utf-8'))
            filepath='%s\%s.mp4' %(movie_path,m.hexdigest())
            with open(filepath,'wb') as f:                        #视频文件,wb保存
                f.write(response.content)
                print('%s 下载成功' %url)
    except Exception:
        pass
        
def main():
    base_url='http://www.xiaohuar.com/list-3-{page_num}.html'
    for i in range(5):
        url=base_url.format(page_num=i)
        pool.submit(get_page,url).add_done_callback(parse_index)
        
if __name__ == '__main__':
    main()


四、爬虫模拟登陆github网站

import requests
import re
# 第三次请求,登录成功之后
    #- 请求之前自己先登录一下,看一下有没有referer
    #- 请求新的url,进行其他操作
    #- 查看用户名在不在里面
    
#第一次请求GET请求
response1 = requests.get(
    "https://github.com/login",
    headers = {
        "User-Agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36",
    },
)
authenticity_token = re.findall('name="authenticity_token".*?value="(.*?)"',response1.text,re.S)
r1_cookies =  response1.cookies.get_dict()                   #获取到的cookie

#第二次请求POST请求
response2 = requests.post(
    "https://github.com/session",
    headers = {
        "Referer": "https://github.com/",
        "User-Agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36",
    },
    data={
            "commit":"Sign in",
            "utf8":"✓",
            "authenticity_token":authenticity_token,
            "login":"zzzzzzzz",
            "password":"xxxx",
zhy..azjash1234
    },
    cookies = r1_cookies
)
print(response2.status_code)
print(response2.history)  #跳转的历史状态码

#第三次请求,登录成功之后,访问其他页面
r2_cookies = response2.cookies.get_dict()           #拿上cookie,表示登陆状态,开始访问页面
response3 = requests.get(
    "https://github.com/settings/emails",
    headers = {
        "Referer": "https://github.com/",
        "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36",
    },
    cookies = r2_cookies,
)
print(response3.text)
print("zzzzzzzz" in response3.text)             #返回True说明就成功了


五、高级用法

1、SSL Cert Verification

import requests
respone=requests.get('https://www.12306.cn',
                     cert=('/path/server.crt','/path/key'))
print(respone.status_code)


2、使用代理

#官网链接: http://docs.python-requests.org/en/master/user/advanced/#proxies
#代理设置:先发送请求给代理,然后由代理帮忙发送(封ip是常见的事情)
import requests
proxies={
    'http':'http://egon:123@localhost:9743',#带用户名密码的代理,@符号前是用户名与密码
    'http':'http://localhost:9743',
    'https':'https://localhost:9743',
}
respone=requests.get('https://www.12306.cn',proxies=proxies)
print(respone.status_code)
#支持socks代理,安装:pip install requests[socks]
import requests
proxies = {
    'http': 'socks5://user:pass@host:port',
    'https': 'socks5://user:pass@host:port'
}
respone=requests.get('https://www.12306.cn',proxies=proxies)
print(respone.status_code)


3、超时设置

#两种超时:float or tuple
#timeout=0.1 #代表接收数据的超时时间
#timeout=(0.1,0.2)#0.1代表链接超时  0.2代表接收数据的超时时间
import requests
respone=requests.get('https://www.baidu.com', timeout=0.0001)


4、认证设置

#官网链接:http://docs.python-requests.org/en/master/user/authentication/
#认证设置:登陆网站是,弹出一个框,要求你输入用户名密码(与alter很类似),此时是无法获取html的
# 但本质原理是拼接成请求头发送
#         r.headers['Authorization'] = _basic_auth_str(self.username, self.password)
#看一看默认的加密方式吧,通常网站都不会用默认的加密设置

import requests
from requests.auth import HTTPBasicAuth
r=requests.get('xxx',auth=HTTPBasicAuth('user','password'))
print(r.status_code)

#HTTPBasicAuth可以简写为如下格式
import requests
r=requests.get('xxx',auth=('user','password'))
print(r.status_code)


5、异常处理

import requests
from requests.exceptions import * #可以查看requests.exceptions获取异常类型
try:
    r=requests.get('http://www.baidu.com',timeout=0.00001)
except ReadTimeout:
    print('===:')
# except ConnectionError:
#     print('-----网络不通')
# except Timeout:
#     print('aaaaa')
except RequestException:
    print('Error')

6、上传文件

import requests
files={'file':open('a.jpg','rb')}
respone=requests.post('http://httpbin.org/post',files=files)
print(respone.status_code)





猜你喜欢

转载自blog.51cto.com/qidian510/2134735