您的位置:首页 > 编程语言 > Python开发

Python爬虫——2.底层操作和请求头、请求代理以及cookie操作

2018-01-09 21:15 423 查看

本文章此节主要讲解:

·爬虫程序urllib2模块底层操作;

·请求头的设置和添加;

·请求代理的种类和类型;

·关于cookie的操作(手动添加/程序自动获取)

一、爬虫底层操作和请求头的设置

1.demo01_爬虫底层操作

虽然urllib2模块是爬虫的底层操作,但并不是程序的底层操作,在其内部的urlopen函数也是有自己封装的内容,实则参数为一个request即请求对象。

# -*- coding:utf-8 -*-
# 引入需要的模块
import urllib2

# 定义url
url='https://www.taobao.com'
# 根据url构建请求对象
request=urllib2.Request(url)

# 使用urllib2的urlopen函数发送请求对象
response=urllib2.urlopen(request)

print response.read()

2.demo02_请求头的设置

客户端在浏览器发送请求给服务器时,会携带请求头,在请求头中有一个User-Agent属性.
User-Agent:用户代理 User Agent,是指浏览器,它的信息包括硬件平台、系统软件、应用软件和用户个人偏好。在X.400电子系统中,用户代理是一种对数据打包、创造分组头,以及编址、传递消息的部件。用户代理并不是仅指浏览器,还包括搜索引擎。
User-Agent其实就是代表用户访问服务器数据的工具,一般情况下,User-Agent是浏览器发起请求时,请求头中包含的数据,主要描述了发送请求的浏览器的版本及内核,操作信息内容等。
①请求头中的数据可以被重新设置。②请求头中可以字典的形式传送自定义数据。

了解都有哪些User-agent

设置请求头

Mozilla/5.0(Macintosh;U;IntelMacOSX10_6_8;en-us)AppleWebKit/534.50(KHTML,likeGecko)Version/5.1Safari/534.50

Mozilla/5.0(Windows;U;WindowsNT6.1;en-us)AppleWebKit/534.50(KHTML,likeGecko)Version/5.1Safari/534.50

Mozilla/5.0(compatible;MSIE9.0;WindowsNT6.1;Trident/5.0;

Mozilla/4.0(compatible;MSIE8.0;WindowsNT6.0;Trident/4.0)

Mozilla/4.0(compatible;MSIE7.0;WindowsNT6.0)

Mozilla/4.0(compatible;MSIE6.0;WindowsNT5.1)

Mozilla/5.0(WindowsNT6.1;rv:2.0.1)Gecko/20100101Firefox/4.0.1

Opera/9.80(Macintosh;IntelMacOSX10.6.8;U;en)Presto/2.8.131Version/11.11

Opera/9.80(WindowsNT6.1;U;en)Presto/2.8.131Version/11.11

Mozilla/5.0(Macintosh;IntelMacOSX10_7_0)AppleWebKit/535.11(KHTML,likeGecko)Chrome/17.0.963.56Safari/535.11

Mozilla/4.0(compatible;MSIE7.0;WindowsNT5.1;Maxthon2.0)

Mozilla/4.0(compatible;MSIE7.0;WindowsNT5.1;TencentTraveler4.0)

Mozilla/4.0(compatible;MSIE7.0;WindowsNT5.1)

Mozilla/4.0(compatible;MSIE7.0;WindowsNT5.1;TheWorld)

Mozilla/4.0(compatible;MSIE7.0;WindowsNT5.1;Trident/4.0;SE2.XMetaSr1.0;SE2.XMetaSr1.0;.NETCLR2.0.50727;SE2.XMetaSr1.0)

Mozilla/4.0(compatible;MSIE7.0;WindowsNT5.1;360SE)


# -*- coding:utf-8 -*-
# 引入需要的模块
import urllib2
import random

# 定义url
url = 'https://www.taobao.com'
# 多个user_agent列表
ua = ['Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SE 2.X MetaSr 1.0; SE 2.X MetaSr 1.0; .NET CLR 2.0.50727; SE 2.X MetaSr 1.0)',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11']

# 随机选取一个user_agent
user_agent = random.choice(ua)
# 定义请求头
my_header = {'User-agent': user_agent}

# 或者使用函数为请求头增加数据
# request=urllib2.Request(url)
# request.add_header('header',my_header)
# 根据url构建请求对象,并设置请求头(设置请求头信息,就是设置浏览器版本和内核信息,让爬虫程序伪装成客户端浏览器)
request = urllib2.Request(url, headers=my_header)

# 使用urllib2的urlopen函数发送请求对象
response = urllib2.urlopen(request)

print response.read()



二、请求方式

1.get请求方式:访问百度搜索

一般情况下都是在Url地址中直接拼接查询字符串的get参数,完成数据的操作

注意:url地址中的中文,在时下较新的浏览器中可以正常处理,但是不一定兼容版本较旧的浏览器,中文的处理一定要进行编码操作

通过urllib.urlencode()的方式,将一个字典数据编辑成k=v形式的数据作为参数拼接给url地址

# -*- coding:utf-8 -*-

'''
get方式访问百度搜索
'''
# 引入需要的模块
import urllib2
import urllib
import random

# 多个user_agent列表
ua = ['Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SE 2.X MetaSr 1.0; SE 2.X MetaSr 1.0; .NET CLR 2.0.50727; SE 2.X MetaSr 1.0)',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11']

# 随机选取一个user_agent
user_agent = random.choice(ua)
# 定义请求头
my_header = {'User-agent': user_agent}
# 定义url,根据抓包工具分析得到的访问路由,由于参可变,所以后面以拼接的方式将参数拼接上来
url = 'https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=0&rsv_idx=1&tn=baidu&'
get_params=raw_input('请输入要搜索的内容:')
# kw='',即浏览器中url路径参数形式
data={'wd':get_params}
# 上面data为字典形式,通过urllib模块的urlencode函数可以将输入的中文编码,并将字典形式转换为k=v,
# 便于在url中显示,以获取数据
data=urllib.urlencode(data)
# 将访问路由url的固定部分(url)和可变参数(data)拼接成完成的full_url
full_url=url+data

# 根据url和请求头创建一个请求对象
request=urllib2.Request(full_url,headers=my_header)
response = urllib2.urlopen(request)
content=response.read()
with open('qiku.html','w') as f:
f.write(content)

print (content)

2.post方式访问有道翻译

1. urllib2发送post请求

定义发送的数据

form_data = {}

将发送的数据转换成字符串编码

data = urllib.urlencode(form_data)

构建Request对象时,如果给data参数赋值,默认发送POST请求

request = urllib2.Request(url, data=data)

urllib2.urlopen(request)# 发送出去的就是POST请求

发送POST请求以及POST请求附带的参数

2. 反[反爬虫]操作

l 确认目标url地址的数据,执行了反爬虫机制!

通过抓包工具,得到目标url地址的具体访问路径Path以及附带的参数,然后将这些数据直接在爬虫程序中进行赋值添加,如果此时访问失败,目标url地址的数据可能执行了反爬虫机制!如~有道在线翻译~我们将所有的请求数据原封不动的添加到爬虫程序中,但是得到了错误的结果:{errorCode:50},有道在线翻译执行了反爬虫机制

l 反[反爬虫]步骤

分析请求中的数据

追踪数据的来源

伪造数据

反机制成功!

# -*- coding:utf-8 -*-

'''

访问url:http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule

请求参数:

    i hello

    from AUTO

    to AUTO

    smartresult dict

    client fanyideskweb

    salt 1515466801319

    sign 78f918a6eb55b77d633cba89bd8385da

    doctype json

    version 2.1

    keyfrom fanyi.web

    action FY_BY_REALTIME

    typoResult false

'''

# 引入需要的模块

import urllib2

import urllib

import random

#######################################################################

import time

E = "fanyideskweb"

# salt盐值

r = str(time.time()*1000 + random.randint(1,10))

# 确定翻译的数据

n = raw_input("请输入要翻译的词语:")

# 确定加密的混淆吗

O = "aNPG!!u6sesA>hBAW1@(-"

# 确定sign参数

import hashlib

sign = hashlib.md5(E + n + r + O).hexdigest()

# 设置有道在线翻译的请求头

headers = {

    #"Host": "fanyi.youdao.com",

    #"Connection": "keep-alive",

    #"Content-Length": "200",

    #"Accept": "application/json, text/javascript, */*; q=0.01",

    #"Origin": "http://fanyi.youdao.com",

    #"X-Requested-With": "XMLHttpRequest",

    #"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",

    "Referer": "http://fanyi.youdao.com/",

    # "Accept-Encoding": "gzip, deflate",

    #"Accept-Language": "zh-CN,zh;q=0.8",

    "Cookie": "OUTFOX_SEARCH_USER_ID_NCOO=2075764580.1728754; OUTFOX_SEARCH_USER_ID=-995280811@10.168.8.63; JSESSIONID=aaaxakcpWa-oo8wK72ydw; fanyi-ad-id=39535; fanyi-ad-closed=1; ___rl__test__cookies=1515468614442i=hell&from=AUTO&to=AUTO&smartresult=dict&client=fanyideskweb&salt=1515468614446&sign=710df1dcc70f91c1b04e795a34704c8e&doctype=json&version=2.1&keyfrom=fanyi.web&action=FY_BY_REALTIME&typoResult=false"

}

#######################################################################

# 定义ua

ua = [

    "Mozilla/5.0(Macintosh;U;IntelMacOSX10_6_8;en-us)AppleWebKit/534.50(KHTML,likeGecko)Version/5.1Safari/534.50",

    "Mozilla/5.0(Windows;U;WindowsNT6.1;en-us)AppleWebKit/534.50(KHTML,likeGecko)Version/5.1Safari/534.50",

    "Mozilla/5.0(compatible;MSIE9.0;WindowsNT6.1;Trident/5.0;",

    "Mozilla/4.0(compatible;MSIE8.0;WindowsNT6.0;Trident/4.0)",

    "Mozilla/4.0(compatible;MSIE7.0;WindowsNT6.0)",

]

# 随机获取一个ua

user_agent = random.choice(ua)

# 定义url地址

url = "http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule"

# 定义表单数据

form_data = {

    "i": n,# 要翻译的词语

    "from": "AUTO", # 词语的翻译之前的语言

    "to": "AUTO", # 词语翻译之后的语言

    "smartresult": "dict", # 数据类型

    "client": "fanyideskweb", # 客户端标识

    "salt": r, # ~~~~可能是~~~时间

    "sign": sign,# ~~~~可能是~~~~md5

    "doctype": "json", # 数据类型

    "version": 2.1,# 版本号

    "keyfrom": "fanyi.web",# 关键字

    "action": "FY_BY_REALTIME",# 行为描述

    "typoResult": False # 结果类型

}

data = urllib.urlencode(form_data)

# 封装请求对象

request = urllib2.Request(url, data=data, headers=headers)

request.add_header("User-agent", user_agent)

# 发送请求获取响应数据

response = urllib2.urlopen(request)

# 打印展示数据

print(response.read())

3.爬取百度图片

确定目标地址[数据访问的真实路径path]

确定参数的含义[通过手工更新参数数据,确定参数的用途]

爬取百度图片页面中展示的图片列表[json字符串数据]【第一次爬取数据】

筛选图片链接[确定图片的规则(http:….jpg/.png),正则表达式筛选目标数据]

img_re_list = re.findall(‘pattern’, content)

循环针对每个图片进行数据爬取【第二次循环爬取数据】

response = urllib2.urlopen(img_url) 

with->open() as f->f.write(response.read())

# -*- coding:utf-8 -*-
# 引入需要的模块
import urllib
import urllib2
import re

# 定义访问路由
url = 'https://image.baidu.com/search/acjson?'
# 定义请求头
my_header = {
#'Host': 'image.baidu.com',
#'Connection': 'keep-alive',
#'Accept': 'text/plain, */*; q=0.01',
#'X-Requested-With': 'XMLHttpRequest',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',
'Referer': 'https://image.baidu.com/search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=result&fr=&sf=1&fmq=1515495630056_R&pv=&ic=0&nc=1&z=&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&word=%E6%B8%85%E9%A3%8E',
#'Accept-Encoding': 'gzip, deflate, br',
#'Accept-Language': 'zh-CN,zh;q=0.9',
'Cookie': 'BDqhfp=%E6%B8%85%E9%A3%8E%26%260-10-1undefined%26%26766%26%262; BAIDUID=01316FFFC8551DCE978112EC7D40746A:FG=1; BIDUPSID=01316FFFC8551DCE978112EC7D40746A; PSTM=1515224694; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; BDRCVFR[X_XKQks0S63]=mk3SLVN4HKm; userFrom=www.so.com; firstShowTip=1; BDRCVFR[-pGxjrCMryR]=mk3SLVN4HKm; cleanHistoryStatus=0; BDRCVFR[dG2JNJb_ajR]=mk3SLVN4HKm; indexPageSugList=%5B%22%E6%B8%85%E9%A3%8E%22%2C%22%E5%94%AF%E7%BE%8E%22%2C%22%E4%BD%A0%22%2C%22%E5%8F%91%22%2C%22%E7%BE%8E%E5%A5%B3%22%2C%22%E5%94%AF%E7%BE%8E%E5%9B%BE%E7%89%87%E5%A4%A7%E5%85%A8%22%5D'
}

form_data={
'tn':'resultjson_com',
'ipn':'rj',
'word':'清风',
'pn':90,
'rn':30,
}
form_data=urllib.urlencode(form_data)
# 定义请求对象
request = urllib2.Request(url+form_data, headers=my_header)

# 发送请求
response = urllib2.urlopen(request)

content = response.read()

url_list=re.findall('"thumbURL":"(.*?)"', content)
print(url_list)

for url in url_list:
print("保存图片%s" % url)
request = urllib2.Request(url, headers=my_header)
response = urllib2.urlopen(request)
img_url = url.replace("/", "_")
with open('bd_img/' + img_url[-50:], "wb") as f:
f.write(response.read())
print("图片%s保存完成" % img_url)


三、自定义opener对象——爬虫底层操作对象

1.为什么要自定义opener对象

python内置模块提供了通用爬虫可以操作的Opener对象,但是如果一旦涉及到自定义的针对各种特定环境的操作,python内置的Opener对象就不能满足我们的需要了,例如客户端和服务器一直在做斗争的爬虫~发爬虫机制:

爬虫~反爬虫~服务器为反爬虫的变态做法:

1.封锁IP

对应策略:反[反爬虫(IP封锁)]:使用代理服务器(肉机),如果使用代理服务器操作的情况下,python内置的opener对象就不能满足我们的需要了

2.需要会话跟踪才能访问的URL地址[session-cookie]

对应策略(对cookie的操作):

①请求中包含cookie数据,可以手工抓包,将cookie数据直接添加到请求头中,实现模拟登陆的情况!手工操作cookie数据~如果服务器出现了即时cookie数据更新,手工操作cookie的的方式就不会太友好了!~python内置的opener对象,不能满足我们直接操作cookie的需求。

关于代理服务器:

代理服务器的类型:

透明代理:服务器能清楚的查看某个IP地址的客户端通过某个IP地址的代理服务器发送了代理请求

匿名代理:服务器能清楚的查看到某个IP地址的代理服务器发起了代理请求,但是查看不到是哪个具体的客户端

高匿代理:服务器分不清这次请求是否代理发送

常见的代理服务器:

免费:提供了代理ip地址和端口port可以免费使用,但是网速一般较慢,存活时间没有保障

收费:提供了代理ip地址和端口port,并且结合账号+密码登录之后才能连接使用,收费的代理~稳定、网速一般较快、动态IP地址跳跃等等

在程序中对于cookie的操作,这就需要我们自定义opener对象,使用python内置了cookielib模块,可以针对请求cookie进行读写操作

实现在程序中自动获取cookie

CookieJar核心模块

FileCookieJar核心模块(继承自上面)

MozillaCookieJar核心模块(继承自上面)

cookie数据直接操作

cookie数据读写操作

2.简单的自定义opener对象的例子

# -*- coding:utf-8 -*-
'''
自定义opener对象的小程序,以爬取"https://www.taobao.com"为例
'''
# 引入需要的模块
import urllib2

# 定义访问路由
url='https://www.taobao.com'
# 定义请求头
my_header={'User-Agent':'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)'}

# 根据请求地址,定义请求对象
request=urllib2.Request(url,headers=my_header)

# 创建一个自定义的handler对象,操作控制http的handler对象
http_handler=urllib2.HTTPHandler()

# 构建一个opener对象
http_opener=urllib2.build_opener(http_handler)

# 发送请求
response=http_opener.open(request)
print response.read()


# -*- coding:utf-8 -*-
'''
自定义opener对象的小程序,以爬取"https://www.taobao.com"为例
'''
# 引入需要的模块
import urllib2

# 定义访问路由
url='https://www.taobao.com'
# 定义请求头
my_header={'User-Agent':'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)'}

# 根据请求地址,定义请求对象
request=urllib2.Request(url,headers=my_header)

# 创建一个自定义的handler对象,操作控制http的handler对象
http_handler=urllib2.HTTPHandler()

# 构建一个opener对象
http_opener=urllib2.build_opener(http_handler)

# 发送请求
response=http_opener.open(request)
print response.read()


3.创建可以操作代理服务器的opener对象

# -*- coding:utf-8 -*-
'''
创建可以操作代理服务器的开锁人(opener对象)
代理服务器包括收费代理和免费代理,分为透明、匿名和高匿三种不同程度和类型的代理,这里以免费代理为例。直接在网上搜索“免费代理”,可以搜到ip和端口
使用收费代理与免费代理相似,只是要加上登录名和密码

免费:提供了代理ip地址和端口port可以免费使用,但是网速一般较慢,存活时间没有保障
使用形式:"http":"ip地址:port端口"

收费:提供了代理ip地址和端口port,并且结合账号+密码登录之后才能连接使用,收费的代理~稳定、网速一般较快、动态IP地址跳跃等等
使用形式:"http":"账户名:密码@ip地址:port端口"
'''
# 引入需要的模块
import urllib2

# 定义访问的url地址
url = 'https://www.taobao.com'
# 定义请求头
my_header = {'User-Agent': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)'}
# 根据定义的访问地址,创建请求对象
request = urllib2.Request(url, headers=my_header)
# 创建可以操作代理服务器的操作对象,这里ProxyHandler是操作代理服务器的操作对象,括号中可直接填写代理服务器的信息
proxy_handler=urllib2.ProxyHandler({"http":"110.73.8.153:8123"})
# proxy_handler = urllib2.ProxyHandler({"http": "admin:123123@110.73.8.153:8123"})
# 根据代理服务器的操作对象,创建opener对象(开锁人)
proxy_opener=urllib2.build_opener(proxy_handler)
response=proxy_opener.open(request)
print response.read()

4.对于opener对象的重新定义,使用python内置的cookielib模块,测试学习程序对cookie的操作。

# -*-coding:utf-8 -*-
# 引入需要的模块
import urllib2
import cookielib

# 定义访问的url地址
url = 'https://www.taobao.com'
# 定义请求头
my_header = {'User-Agent': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)'}

request=urllib2.Request(url,headers=my_header)
# 定义一个cookie核心对象
cookie=cookielib.CookieJar()
# 自定义一个handler对象,可以操作cookie
cookie_handler=urllib2.HTTPCookieProcessor(cookie)

# 定义opener
cookie_opener=urllib2.build_opener(cookie_handler)
# 发送请求
response=cookie_opener.open(request)

# 这是一个小程序,专门用于测试cookielib模块对于cookie数据的操作
# 重点不在于获取爬取的数据,而是在于cookie中的数据
for item in cookie:
print("%s-%s" % (item.name, item.value))
# "{} - {}".format("hello", "world")

'''打印结果:thw-cn
    '''

# -*-coding:utf-8 -*-
# 引入需要的模块
import urllib2
import cookielib

# 定义访问的url地址
url = 'https://www.taobao.com'
# 定义请求头
my_header = {'User-Agent': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)'}

request=urllib2.Request(url,headers=my_header)
# 定义一个cookie核心对象
cookie=cookielib.CookieJar()
# 自定义一个handler对象,可以操作cookie
cookie_handler=urllib2.HTTPCookieProcessor(cookie)

# 定义opener
cookie_opener=urllib2.build_opener(cookie_handler)
# 发送请求
response=cookie_opener.open(request)

# 这是一个小程序,专门用于测试cookielib模块对于cookie数据的操作
# 重点不在于获取爬取的数据,而是在于cookie中的数据
for item in cookie:
print("%s-%s" % (item.name, item.value))
# "{} - {}".format("hello", "world")

'''打印结果:thw-cn
    '''

4.对于opener对象的重新定义,使用python内置的cookielib模块,完成程序对于cookie的操作(直接获取并保存)

# -*-coding:utf-8 -*-
# 引入需要的模块
import urllib2
import cookielib

# 定义访问的url地址
url = 'https://www.taobao.com'
# 定义请求头
my_header = {'User-Agent': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)'}

# 定义请求对象
request=urllib2.Request(url,headers=my_header)
# 获取cookie对象,使用MozillaCookieJar可以直接定义将cookie保存所在的文件名及位置
cookie=cookielib.MozillaCookieJar("demo09.txt")
# 定义操作cookie的对象
cookie_handler=urllib2.HTTPCookieProcessor(cookie)
# 定义opener
cookie_opener=urllib2.build_opener(cookie_handler)
# 发送请求
response=cookie_opener.open(request)
# 保存cookie数据
cookie.save()

'''
文件demo09.txt的内容如下:
# Netscape HTTP Cookie File
# http://curl.haxx.se/rfc/cookie_spec.html # This is a generated file!  Do not edit.
.taobao.com    TRUE   /  FALSE  1547039357 thw    cn
'''

5.对于opener对象的重新定义,使用python内置的cookielib模块,完成程序对于cookie的操作(直接操作使用上一步获取的cookie)

# -*-coding:utf-8 -*-
# 引入需要的模块
import urllib2
import cookielib

# 定义访问的url地址
url = 'https://www.taobao.com'
# 定义请求头
my_header = {'User-Agent': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)'}

# 定义请求对象
request=urllib2.Request(url,headers=my_header)
# 获取cookie对象,使用MozillaCookieJar,若需要保存cookie数据,则括号中写文件名,若是获取cookie数据,则不写
cookie=cookielib.MozillaCookieJar()
# 下载cookie数据
cookie.load('demo09.txt')
# 创建Handler操作对象
cookie_handler = urllib2.HTTPCookieProcessor(cookie)
# 创建opener对象
cookie_opener = urllib2.build_opener(cookie_handler)

# 访问目标地址
response = cookie_opener.open(request)

print(response.read())
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: