网络爬虫--requests、post、解密、Cookie、Session、IP代理

网络爬虫的定义

网络爬虫是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。

根据使用场景,网络爬虫可分为通用爬虫和聚焦爬虫两种。

通用爬虫

通用网络爬虫
是捜索引擎抓取系统(Baidu、Google、Yahoo等)的重要组成部分。主要目的是将互联网上的网页下载到本地,形成一个互联网内容的镜像备份。
通用搜索引擎(Search Engine)工作原理

  • 什么是搜索引擎?

搜索引擎(Search
Engine)是指根据一定的策略、运用特定的计算机程序从互联网上搜集信息,在对信息进行组织和处理后,为用户提供检索服务,将用户检索相关的信息展示给用户的系统。

通用网络爬虫:从互联网中搜集网页,采集信息,这些网页信息用于为搜索引擎建立索引从而提供支持,它决定着整个引擎系统的内容是否丰富,信息是否即时,因此其性能的优劣直接影响着搜索引擎的效果。

  • 第一步:抓取网页
    搜索引擎网络爬虫的基本工作流程如下:

首先选取一部分的种子URL,将这些URL放入待抓取URL队列;
取出待抓取URL,解析DNS得到主机的IP,并将URL对应的网页下载下来,存储进已下载网页库中,并且将这些URL放进已抓取URL队列。
分析已抓取URL队列中的URL,分析其中的其他URL,并且将URL放入待抓取URL队列,从而进入下一个循环…

在这里插入图片描述
搜索引擎如何获取一个新网站的URL:

  1. 新网站向搜索引擎主动提交网址:(如http://zhanzhang.baidu.com/linksubmit/url)
  2. 在其他网站上设置新网站外链(尽可能处于搜索引擎爬虫爬取范围)
  3. 搜索引擎和DNS解析服务商(如DNSPod等)合作,新网站域名将被迅速抓取。
    但是搜索引擎蜘蛛的爬行是被输入了一定的规则的,它需要遵从一些命令或文件的内容,如标注为nofollow的链接,或者是Robots协议。
    Robots协议(也叫爬虫协议、机器人协议等),全称是“网络爬虫排除标准”(Robots Exclusion Protocol),网站通过Robots协议告诉搜索引擎哪些页面可以抓取,哪些页面不能抓取,例如:
    淘宝网:https://www.taobao.com/robots.txt
    腾讯网: http://www.qq.com/robots.txt
  • 第二步:数据存储

搜索引擎通过爬虫爬取到的网页,将数据存入原始页面数据库。其中的页面数据与用户浏览器得到的HTML是完全一样的。
搜索引擎蜘蛛在抓取页面时,也做一定的重复内容检测,一旦遇到访问权重很低的网站上有大量抄袭、采集或者复制的内容,很可能就不再爬行。

  • 第三步:预处理
    搜索引擎将爬虫抓取回来的页面,进行各种步骤的预处理。
    提取文字
    中文分词
    消除噪音(比如版权声明文字、导航条、广告等……)
    索引处理
    链接关系计算
    特殊文件处理

    除了HTML文件外,搜索引擎通常还能抓取和索引以文字为基础的多种文件类型,如 PDF、Word、WPS、XLS、PPT、TXT 文件等。我们在搜索结果中也经常会看到这些文件类型。
    但搜索引擎还不能处理图片、视频、Flash 这类非文字内容,也不能执行脚本和程序。

  • 第四步:提供检索服务,网站排名
    搜索引擎在对信息进行组织和处理后,为用户提供关键字检索服务,将用户检索相关的信息展示给用户。
    同时会根据页面的PageRank值(链接的访问量排名)来进行网站排名,这样Rank值高的网站在搜索结果中会排名较前,当然也可以直接使用 Money 购买搜索引擎网站排名,简单粗暴。
    在这里插入图片描述但是,这些通用性搜索引擎也存在着一定的局限性:
    1.通用搜索引擎所返回的结果都是网页,而大多情况下,网页里90%的内容对用户来说都是无用的。
    2.不同领域、不同背景的用户往往具有不同的检索目的和需求,搜索引擎无法提供针对具体某个用户的搜索结果。
    3.万维网数据形式的丰富和网络技术的不断发展,图片、数据库、音频、视频多媒体等不同数据大量出现,通用搜索引擎对这些文件无能为力,不能很好地发现和获取。
    4.通用搜索引擎大多提供基于关键字的检索,难以支持根据语义信息提出的查询,无法准确理解用户的具体需求。

聚焦爬虫

聚焦爬虫,是"面向特定主题需求"的一种网络爬虫程序,它与通用搜索引擎爬虫的区别在于:
聚焦爬虫在实施网页抓取时会对内容进行处理筛选,尽量保证只抓取与需求相关的网页信息。

网络爬虫抓取过程可以理解为模拟浏览器操作的过程。浏览器的主要功能是向服务器发出请求,在浏览器窗口中展示您选择的网络资源,HTTP是一套计算机通过网络进行通信的规则。

requests

import requests

# 1、定义起始url 需要爬取的url
base_url = "https://www.baidu.com/more/"

# 2、发起请求 接收相应信息 返回的是200的相应 表示请求正常
response = requests.get(base_url)

# 3、获取爬取到的文本信息 是字符串
# html = response.text
# print(html)

# 4、获取网页内容 content返回的是 bytes类型
# 然后使用decode进行解码成字符串
html = response.content.decode("utf-8")
print(html)

# 5、存储页面数据
with open("baidu.html", "w", encoding="utf-8") as f:
    f.write(html)

携带参数的第一种方式

import requests
from urllib import parse

# 问号后面的都是参数
base_url = "https://search.sina.com.cn/?"

# 定义参数字典
params = {
    "q": "nba",
    "c": "news",
    "from": "channel",
    "ie": "utf-8"
}

# 将字典转换url编码格式
params_url = parse.urlencode(params)
# print(params_url)

# 拼接完整的url
full_url = base_url + params_url
# print(full_url)

# 对完整的url发起请求
response = requests.get(full_url)
html = response.text
print(html)

'''
总结:
1、找到爬取数据的网页url
在网页中点击右键检查,点击network,点击all,左上角刷新网页,然后数据就会出来
2、点击第一个网页信息
右边的response是相应的页面信息主要是html,headers是发起请求需要携带的数据
headers中:
(1)request url 是网页请求的url 
(2)response headers 是相应的结果参数
(3)request headers 是发起请求需要携带的东西
(4)string params 是get请求携带的参数  
3、携带参数 以及request url 使用requests发起请求 格式见本文件 
'''

携带参数的第二种方式

import requests

# 问号后面的都是参数
base_url = "https://search.sina.com.cn/?"

# 定义参数字典
params = {
    "q": "nba",
    "c": "news",
    "from": "channel",
    "ie": "utf-8"
}

# 将参数使用params接收
response = requests.get(base_url, params=params)
html = response.text
print(html)  # 查看请求的html
print(response.url)   # 查看请求的url

携带参数的第三种方式

import requests
from urllib import parse

# 问号后面的都是参数
base_url = "https://search.sina.com.cn/?q=A%B9%C9&range=all&c=news&sort=time"

# 对完整的url发起请求
response = requests.get(base_url)
html = response.text
print(html)  # 查看请求的html
print(response.url)   # 查看请求的url

'''
总结:
一般使用的是后两种方式发起请求,方便简洁
如果携带的参数很多,则建议使用第二种方式
'''

注意:

dict1 = {"k": "python", "v": "蟒蛇"}

# 当代码出现 获取不到的情况 你又不想终止你的代码运行 可以使用get

print(dict1.get("kw"))  # 没有获取到 返回None

# 当必须一定要 有kw的时候 就要用["kw"] 没有它程序不能 运行

# print(dict1["kw"])  # 没有找到 报 KeyError: 'kw'

response中的方法

# 发起请求 添加headers 请求头 让服务器知道是浏览器访问
response = requests.get(base_url, params=params, headers=headers)

print(response.text)  # 获取字符串文本信息
print(response.content)  # 获取字节流 bytes类型
print(response.url)  # 获取请求的url
print(response.encoding)  # 获取编码
print(response.status_code)  # 获取状态码
print(response.headers)  # 获取响应头

"""
总结:
携带参数的请求,如果说获取不到指定的页面数据,则需要加上请求头
第一步:请求头中添加User_Agent, headers 是一个字典,添加完之后
看看能不能获取到指定的数据,如果不能则需要将所有的请求头添加到headers
"""

post请求

# 注意: 一般情况下post请求的url和网页的url不一致
    base_url = "https://fanyi.baidu.com/sug"

    # 定义携带的参数
    data = {"kw": kw}

    # 发起post请求 data=None, json=None,
    response = requests.post(base_url, data=data)

json

'''
json.loads: 将字符串转换为json数据(字典,列表)
json.dumps: 将json数据转换为字符串
json.cn: 格式化字符串 必须是字符串,不能是其他类型
'''

获取json数据

response= requests.post(base_url, data=data).content.decode("utf-8")
#方式一
# 将字符串转换为json数据 此时这里是字典
    json_data = json.loads(response)
    
#方式二
# 获取json数据
    json_data = response.json()

补充

list1 = []
list2 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

for i in list2:
    list1 += i

print(list1)

'''
总结:
列表相加 可以使用+=号, city_list += city_list1
判断某个信息 时候成功获取到,接口返回的信息 会告诉你,只有在获取到信息之后 
我们才对指定 信息进行获取 ,如果不这样的话 会报错,影响代码正常运行,
此时应该写异常处理
'''

解密

import requests
import time
import random
import hashlib

def md5(value):
    # 创建MD5对象
    md5_obj = hashlib.md5()
    # 加密字符串
    md5_obj.update(bytes(value, encoding="utf-8"))
    # 进行16位的加密
    sign = md5_obj.hexdigest()
    return sign

def youdao(i):
    # 获取salt
    salt = str(int(time.time() * 1000)) + str(random.randint(0, 9))
    # print(salt)
    # 获取sign
    sign1 = "fanyideskweb" + i + salt + "@6f#X3=cCuncYssPsuRUE"
    sign = md5(sign1)
    # 定义data参数
    data = {
        "i": i,
        # "from": "AUTO",
        # "to": "AUTO",
        # "smartresult": "dict",
        "client": "fanyideskweb",
        "salt": salt,
        "sign": sign,
        # "ts": "1558514897639",
        # "bv": "cf156b581152bd0b259b90070b1120e6",
        # "doctype": "json",
        # "version": "2.1",
        "keyfrom": "fanyi.web",
        # "action": "FY_BY_REALTlME"
    }

    # 加上请求头 浏览器信息
    headers = {
        # "Accept": "application/json, text/javascript, */*; q=0.01",
        # "Accept-Encoding": "gzip, deflate",
        # "Accept-Language": "zh-CN,zh;q=0.9",
        # "Connection": "keep-alive",
        # "Content-Length": "238",
        # "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
        "Cookie": "OUTFOX_SEARCH_USER_ID=1007772075@10.168.8.76; OUTFOX_SEARCH_USER_ID_NCOO=1844201936.6123636; _ga=GA1.2.1939912746.1552966532; JSESSIONID=aaaB9UfpkFL02gnEynoRw; ___rl__test__cookies=1558514897636",
        # "Host": "fanyi.youdao.com",
        # "Origin": "http://fanyi.youdao.com",
        "Referer": "http://fanyi.youdao.com/",
        "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36",
        # "X-Requested-With": "XMLHttpRequest"
    }

    # 定义起始url
    base_url = "http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule"

    # 发送请求
    response = requests.post(base_url, data=data, headers=headers)
    # 获取response里面的json数据
    json_data = response.json()
    print(json_data)
    print(type(json_data))


if __name__ == '__main__':
    i = input("请输入需要翻译的内容:")
    # i = "banana"
    youdao(i)

"""
遇到的问题1:
""只携带参数data 发起请求的时候,请求不到数据,出现{'errorCode'"": ""50},",",
此时的解决方案是:加上请求头浏览器信息 再次发起请求 
""问题2:还是获取不到信息 {'errorCode'"": ""50}",",
解决的方案是:把所有的请求头信息添加到headers中
"""

# i: banana
# client: fanyideskweb
# salt: 15585168560444
# sign: da50e3193cda496e1455ff28c1bb21b1
# keyfrom: fanyi.web
#
# i: apple
# "client": "fanyideskweb",
# "salt": "15585148976393",
# "sign": "147950af9758d1e79aeaacd4ff27d14d",
# "keyfrom": "fanyi.web",
#
#
# salt:  需要看一下 是否需要加密
# sign: 也要看一下是否需要加密

# 首要解决的问题是salt和sign生成的过程
'''
salt = o.salt = i = r + parseInt(10 * Math.random(), 10)
"" + (new Date).getTime() + parseInt(10 * Math.random(), 10)  js
= "" + int(time.time() * 1000) + random.randint(0, 9)

o = r.generateSaltSign(t) = r(t)
r.generateSaltSign(t) = t.generateSaltSign(t) = r(t)
{
    ts: r,
    bv: t,
    salt: i,
    sign: n.md5("fanyideskweb" + e + i + "@6f#X3=cCuncYssPsuRUE")
}


e = t = "apple" 需要翻译的内容

var r = function(e)
    {
            var
        t = n.md5(navigator.appVersion),
            r = "" + (new Date).getTime(),
                i = r + parseInt(10 * Math.random(), 10);
        return {
            ts: r,
            bv: t,
            salt: i,
            sign: n.md5("fanyideskweb" + e + i + "@6f#X3=cCuncYssPsuRUE")
    }
};


长度比较:
15585816225096   python
15585148976393   js
15585822104216

sign = o.sign
= n.md5("fanyideskweb" + e + i + "@6f#X3=cCuncYssPsuRUE")
= md5("fanyideskweb" + "apple" + salt + "@6f#X3=cCuncYssPsuRUE")
'''

Cookie

# 添加含有cookie的请求头
headers = {
    "Cookie": "anonymid=junimtwwu50d24; _r01_=1; _de=5F71EE4FAB787F2D9124C42004FCABA0; depovince=GW; jebecookies=b450d427-3a0e-4aa8-8378-d3ada01f9f03|||||; JSESSIONID=abcmZXoIdRY6Weth6sJRw; ick_login=49d3b618-6b47-4a21-b233-16b3fc3afbef; p=d577c793658cfc4bf9ad91e52f20586a1; first_login_flag=1; ln_uact=18679030315; ln_hurl=http://head.xiaonei.com/photos/0/0/men_main.gif; t=2f7dc309b51521affb888e36a312f0891; societyguester=2f7dc309b51521affb888e36a312f0891; id=964508591; xnsid=1cb3fa4a; ver=7.0; loginfrom=null; jebe_key=a56cca4b-9248-423e-848b-5eebe8ee1750%7C8562fb69c05d6f5ab11983a626d37548%7C1558591573088%7C1%7C1558591573577; wp_fold=0"
}

# 携带cookie发起请求
response = requests.get(base_url, headers=headers)


'''
分析:携带cookie可以获取到想要的信息,这是因为cookie中含有登录的信息,
服务器会接收登录信息 然后进行登录操作,保存登录状态,然后可以获取指定的个人网页信息
'''

# 获取cookie返回的是 cookiejar类型
cookiejar = response.cookies

# 将cookies转换为字典的格式
cookie_dict = requests.utils.dict_from_cookiejar(cookiejar)

Session

import requests

# 1、创建session对象
ssion = requests.session()

# 2、创建需要登录的信息字典
data = {
    "email": "aaaaaaa",
    "password": "bbbbbbb"
}
# 3、使用ssion进行post登录 需要找到登录的接口
# 得到的是含有登录信息的ssion
ssion.post("http://www.renren.com/PLogin.do", data=data)

# 4、使用含有登录的信息的ssion 进行获取个人网页信息
response = ssion.get("http://www.renren.com/964508591/profile")

# 5、获取个人信息
html = response.text
print(html)

IP代理

import requests


# 定义一个代理字典
proxies = {
    # "http": "http://112.85.128.110:9999",
    "https": "http://61.142.72.154:30074"
}


response = requests.get("https://www.baidu.com", proxies=proxies)
print(response)
print(response.text)


'''
http代理 : 可以访问https的url,因为http使用的是http的代理服务器
https代理: 拒绝访问https的url(可能访问成功,也可能不成功), 为了安全考虑,
        很多人使用https的代理服务器,所以会强行关闭远程连接
'''
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值