爬虫基础

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了爬虫基础相关的知识,希望对你有一定的参考价值。

request 模块



Requests: 让 HTTP 服务人类


虽然Python的标准库中 urllib 模块已经包含了平常我们使用的大多数功能,但是它的 API 使用起来让人感觉不太好,而 Requests 自称 "HTTP for Humans",说明使用更简洁方便。


Requests 唯一的一个非转基因的 Python HTTP 库,人类可以安全享用:)


Requests 继承了urllib的所有特性。Requests支持HTTP连接保持和连接池,支持使用cookie保持会话,支持文件上传,支持自动确定响应内容的编码,支持国际化的 URL 和 POST 数据自动编码。


requests 的底层实现其实就是 urllib


Requests的文档非常完备,中文文档也相当不错。Requests能完全满足当前网络的需求,支持Python 2.6--3.5,而且能在PyPy下完美运行。


开源地址:https://github.com/kennethreitz/requests


中文文档 API: http://docs.python-requests.org/zh_CN/latest/index.html


安装方式


利用 pip 安装 或者利用 easy_install 都可以完成安装:


$ pip install requests


$ easy_install requests

基本GET请求(headers参数 和 parmas参数)


1. 最基本的GET请求可以直接用get方法


response = requests.get("http://www.baidu.com/")


# 也可以这么写

# response = requests.request("get", "http://www.baidu.com/")

2. 添加 headers 和 查询参数


如果想添加 headers,可以传入headers参数来增加请求头中的headers信息。如果要将参数放在url中传递,可以利用 params 参数。



import requests


kw = {‘wd‘:‘长城‘}


headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}


# params 接收一个字典或者字符串的查询参数,字典类型自动转换为url编码,不需要urlencode()

response = requests.get("http://www.baidu.com/s?", params = kw, headers = headers)


# 查看响应内容,response.text 返回的是Unicode格式的数据

print (response.text)


# 查看响应内容,response.content返回的字节流数据

print (respones.content)


# 查看完整url地址

print (response.url)


# 查看响应头部字符编码

print (response.encoding)


# 查看响应码

print (response.status_code)


使用response.text 时,Requests 会基于 HTTP 响应的文本编码自动解码响应内容,大多数 Unicode 字符集都能被无缝地解码。


使用response.content 时,返回的是服务器响应数据的原始二进制字节流,可以用来保存图片等二进制文件。


小栗子


通过requests获取新浪首页


#coding=utf-8

import  requests

response = requests.get("http://www.sina.com")

print(response.request.headers)

print(response.content.decode())


通过requests获取网络上图片的大小


from io import BytesIO,StringIO

import requests

from PIL import Image

img_url = "http://imglf1.ph.126.net/pWRxzh6FRrG2qVL3JBvrDg==/6630172763234505196.png"

response = requests.get(img_url)

f = BytesIO(response.content)

img = Image.open(f)

print(img.size)


理解一下 BytesIO 和StringIO


很多时候,数据读写不一定是文件,也可以在内存中读写。

StringIO顾名思义就是在内存中读写str。

BytesIO 就是在内存中读写bytes类型的二进制数据


例子中如果使用StringIO 即f = StringIO(response.text)会产生"cannot identify image file"的错误

当然上述例子也可以把图片存到本地之后再使用Image打开来获取图片大小


Cookies 和 Sission


Cookies


如果一个响应中包含了cookie,那么我们可以利用 cookies参数拿到:



import requests


response = requests.get("http://www.baidu.com/")


# 7\. 返回CookieJar对象:

cookiejar = response.cookies


# 8\. 将CookieJar转为字典:

cookiedict = requests.utils.dict_from_cookiejar(cookiejar)


print (cookiejar)


print (cookiedict)

运行结果:


<RequestsCookieJar[<Cookie BDORZ=27315 for .baidu.com/>]>


{‘BDORZ‘: ‘27315‘}

session


基本POST请求(data参数)


1. 最基本post方法


response = requests.post("http://www.baidu.com/", data = data)

2. 传入data数据


对于 POST 请求来说,我们一般需要为它增加一些参数。那么最基本的传参方法可以利用 data 这个参数。


import requests


formdata = {

    "type":"AUTO",

    "i":"i love python",

    "doctype":"json",

    "xmlVersion":"1.8",

    "keyfrom":"fanyi.web",

    "ue":"UTF-8",

    "action":"FY_BY_ENTER",

    "typoResult":"true"

}


url = "http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule&smartresult=ugc&sessionFrom=null"


headers={ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36"}


response = requests.post(url, data = formdata, headers = headers)


print (response.text)


# 如果是json文件可以直接显示

print (response.json())

运行结果


{"type":"EN2ZH_CN","errorCode":0,"elapsedTime":3,"translateResult":[[{"src":"i love python","tgt":"我喜欢python"}]],"smartResult":{"type":1,"entries":["","肆文","","","高德纳","",""]}}


{‘type‘: ‘EN2ZH_CN‘, ‘errorCode‘: 0, ‘elapsedTime‘: 3, ‘translateResult‘: [[{‘src‘: ‘i love python‘, ‘tgt‘: ‘我喜欢python‘}]], ‘smartResult‘: {‘type‘: 1, ‘entries‘: [‘‘, ‘肆文‘, ‘‘, ‘‘, ‘高德纳‘, ‘‘, ‘‘]}}

代理(proxies参数)


如果需要使用代理,你可以通过为任意请求方法提供 proxies 参数来配置单个请求:


import requests


# 根据协议类型,选择不同的代理

proxies = {

  "http": "http://12.34.56.79:9527",

  "https": "http://12.34.56.79:9527",

}


response = requests.get("http://www.baidu.com", proxies = proxies)

print response.text

也可以通过本地环境变量 HTTP_PROXY 和 HTTPS_PROXY 来配置代理:


export HTTP_PROXY="http://12.34.56.79:9527"

export HTTPS_PROXY="https://12.34.56.79:9527"

私密代理验证(特定格式) 和 Web客户端验证(auth 参数)


私密代理



import requests


# 如果代理需要使用HTTP Basic Auth,可以使用下面这种格式:

proxy = { "http": "mr_mao_hacker:[email protected]:16816" }


response = requests.get("http://www.baidu.com", proxies = proxy)


print (response.text)

web客户端验证


如果是Web客户端验证,需要添加 auth = (账户名, 密码)


import requests


auth=(‘test‘, ‘123456‘)


response = requests.get(‘http://192.168.199.107‘, auth = auth)


print (response.text)

Cookies 和 Sission


Cookies


如果一个响应中包含了cookie,那么我们可以利用 cookies参数拿到:



import requests


response = requests.get("http://www.baidu.com/")


# 7\. 返回CookieJar对象:

cookiejar = response.cookies


# 8\. 将CookieJar转为字典:

cookiedict = requests.utils.dict_from_cookiejar(cookiejar)


print (cookiejar)


print (cookiedict)

运行结果:


<RequestsCookieJar[<Cookie BDORZ=27315 for .baidu.com/>]>


{‘BDORZ‘: ‘27315‘}

session


在 requests 里,session对象是一个非常常用的对象,这个对象代表一次用户会话:从客户端浏览器连接服务器开始,到客户端浏览器与服务器断开。


会话能让我们在跨请求时候保持某些参数,比如在同一个 Session 实例发出的所有请求之间保持 cookie 。


实现人人网登录


import requests


# 1\. 创建session对象,可以保存Cookie值

ssion = requests.session()


# 2\. 处理 headers

headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}


# 3\. 需要登录的用户名和密码

data = {"email":"[email protected]", "password":"alarmchime"}


# 4\. 发送附带用户名和密码的请求,并获取登录后的Cookie值,保存在ssion里

ssion.post("http://www.renren.com/PLogin.do", data = data)


# 5\. ssion包含用户登录后的Cookie值,可以直接访问那些登录后才可以访问的页面

response = ssion.get("http://www.renren.com/410043129/profile")


# 6\. 打印响应内容

print (response.text)



处理HTTPS请求 SSL证书验证


Requests也可以为HTTPS请求验证SSL证书:


要想检查某个主机的SSL证书,你可以使用 verify 参数(也可以不写)

import requests

response = requests.get("https://www.baidu.com/", verify=True)


# 也可以省略不写

# response = requests.get("https://www.baidu.com/")

print (r.text)

运行结果:


<!DOCTYPE html>

<!--STATUS OK--><html> <head><meta http-equiv=content-type

content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible

content=IE=Edge>百度一下,你就知道 ....

如果SSL证书验证不通过,或者不信任服务器的安全证书,则会报出SSLError,据说 12306 证书是自己做的:



来测试一下:


import requests

response = requests.get("https://www.12306.cn/mormhweb/")

print (response.text)

果然:


SSLError: ("bad handshake: Error([(‘SSL routines‘, ‘ssl3_get_server_certificate‘, ‘certificate verify failed‘)],)",)


如果我们想跳过 12306 的证书验证,把 verify 设置为 False 就可以正常请求了。


r = requests.get("https://www.12306.cn/mormhweb/", verify = False)





添加更多的Header信息


在 HTTP Request 中加入特定的 Header,来构造一个完整的HTTP请求消息。


可以通过调用Request.add_header() 添加/修改一个特定的header 也可以通过调用Request.get_header()来查看已有的header。


添加一个特定的header

随机添加/修改User-Agent


[email protected]:/data/server/spider# cat spider_ua.py

import urllib.request

import random

url = "http://www.itcast.cn"

ua_list = [

    "Mozilla/5.0 (Windows NT 6.1; ) Apple.... ",

    "Mozilla/5.0 (X11; CrOS i686 2268.111.0)... ",

    "Mozilla/5.0 (Macintosh; U; PPC Mac OS X.... ",

    "Mozilla/5.0 (Macintosh; Intel Mac OS... "

]

user_agent = random.choice(ua_list)

print(user_agent)

request = urllib.request.Request(url)

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

response = urllib.request.urlopen(request)

html = response.read()

print(html)




接下来,让我们真正迈向我们的爬虫之路吧!


urllib库的基本使用


所谓网页抓取,就是把URL地址中指定的网络资源从网络流中读取出来,保存到本地。 在Python中有很多库可以用来抓取网页,我们先学习urllib。


在 python2 中,urllib 被分为urllib,urllib2等


urlopen


我们先来段代码:


# urllib_request.py


# 导入urllib.request 库

import urllib.request


# 向指定的url发送请求,并返回服务器响应的类文件对象

response = urllib.request.urlopen("http://www.baidu.com")


# 类文件对象支持文件对象的操作方法,如read()方法读取文件全部内容,返回字符串

html = response.read()


# 打印字符串

print (html)

执行写的python代码,将打印结果


[email protected] ~$: python urllib_request.py

实际上,如果我们在浏览器上打开百度主页, 右键选择“查看源代码”,你会发现,跟我们刚才打印出来的是一模一样。也就是说,上面的4行代码就已经帮我们把百度的首页的全部代码爬了下来。


一个基本的url请求对应的python代码真的非常简单。


Request


在我们第一个例子里,urlopen()的参数就是一个url地址;


但是如果需要执行更复杂的操作,比如增加HTTP报头,必须创建一个 Request 实例来作为urlopen()的参数;而需要访问的url地址则作为 Request 实例的参数。


我们编辑urllib_request.py


# urllib_request.py


import urllib.request


# url 作为Request()方法的参数,构造并返回一个Request对象

request = urllib.request.Request("http://www.baidu.com")


# Request对象作为urlopen()方法的参数,发送给服务器并接收响应

response = urllib.request.urlopen(request)


html = response.read().decode()


print (html)

运行结果是完全一样的:


新建Request实例,除了必须要有 url 参数之外,还可以设置另外两个参数:


data(默认空):是伴随 url 提交的数据(比如要post的数据),同时 HTTP 请求将从 "GET"方式 改为 "POST"方式。


headers(默认空):是一个字典,包含了需要发送的HTTP报头的键值对。


这两个参数下面会说到。


User-Agent


但是这样直接用urllib给一个网站发送请求的话,确实略有些唐突了,就好比,人家每家都有门,你以一个路人的身份直接闯进去显然不是很礼貌。而且有一些站点不喜欢被程序(非人为访问)访问,有可能会拒绝你的访问请求。


但是如果我们用一个合法的身份去请求别人网站,显然人家就是欢迎的,所以我们就应该给我们的这个代码加上一个身份,就是所谓的User-Agent头。


浏览器 就是互联网世界上公认被允许的身份,如果我们希望我们的爬虫程序更像一个真实用户,那我们第一步,就是需要伪装成一个被公认的浏览器。用不同的浏览器在发送请求的时候,会有不同的User-Agent头。 urllib默认的User-Agent头为:Python-urllib/x.y(x和y是Python主版本和次版本号,例如 Python-urllib/2.7)

#urllib_request.py


import urllib.request


url = "http://www.itcast.cn"


#IE 9.0 的 User-Agent,包含在 ua_header里

ua_header = {"User-Agent" : "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;"}


#  url 连同 headers,一起构造Request请求,这个请求将附带 IE9.0 浏览器的User-Agent

request = urllib.request.Request(url, headers = ua_header)


# 向服务器发送这个请求

response = urllib.request.urlopen(request)


html = response.read()

print (html)

添加更多的Header信息


在 HTTP Request 中加入特定的 Header,来构造一个完整的HTTP请求消息。


可以通过调用Request.add_header() 添加/修改一个特定的header 也可以通过调用Request.get_header()来查看已有的header。


添加一个特定的header

# urllib_headers.py


import urllib.request


url = "http://www.itcast.cn"


#IE 9.0 的 User-Agent

header = {"User-Agent" : "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;"}

request = urllib.request.Request(url, headers = header)


#也可以通过调用Request.add_header() 添加/修改一个特定的header

request.add_header("Connection", "keep-alive")


# 也可以通过调用Request.get_header()来查看header信息

# request.get_header(header_name="Connection")


response = urllib.request.urlopen(request)


print (response.code) #可以查看响应状态码

html = response.read().decode()


print (html)

随机添加/修改User-Agent

# urllib_add_headers.py


import urllib

import random


url = "http://www.itcast.cn"


ua_list = [

    "Mozilla/5.0 (Windows NT 6.1; ) Apple.... ",

    "Mozilla/5.0 (X11; CrOS i686 2268.111.0)... ",

    "Mozilla/5.0 (Macintosh; U; PPC Mac OS X.... ",

    "Mozilla/5.0 (Macintosh; Intel Mac OS... "

]


user_agent = random.choice(ua_list)


request = urllib.request.Request(url)


#也可以通过调用Request.add_header() 添加/修改一个特定的header

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


# get_header()的字符串参数,第一个字母大写,后面的全部小写

request.get_header("User-agent")


response = urllib.request.urlopen(requestr)


html = response.read()

print (html)


本文出自 “梦女孩” 博客,请务必保留此出处http://dreamgirl1314.blog.51cto.com/1159474/1980930

以上是关于爬虫基础的主要内容,如果未能解决你的问题,请参考以下文章

爬虫基础知识

爬虫基础知识

0基础学爬虫爬虫基础之抓包工具的使用

0基础学爬虫爬虫基础之网页解析库的使用

0基础学爬虫爬虫基础之自动化工具 Pyppeteer 的使用

0基础学爬虫爬虫基础之自动化工具 Selenium 的使用