虽然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()
客户端在浏览器发送请求给服务器时,会携带请求头,在请求头中有一个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()
一般情况下都是在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)
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; [email protected]; 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())
确定目标地址[数据访问的真实路径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)
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数据读写操作
# -*- 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()
# -*- 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:[email protected]:8123"}) # 根据代理服务器的操作对象,创建opener对象(开锁人) proxy_opener=urllib2.build_opener(proxy_handler) response=proxy_opener.open(request) print response.read()
# -*-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 '''
# -*-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 '''
# -*-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())