爬虫技术(1) 前置知识与架构

1. requests 库的使用

安装

pip install requests

发送请求

(1)请求方式

  • Get 查看资源
  • POST 增加资源
  • PUT 修改资源
  • PATCH 少量修改资源
  • DELETE 删除资源
  • HEAD 查看响应头
  • OPTIONS 查看可用的请求方法

(2)请求api

  • get 方式 后面跟拼接参数: requests.get(url, params={'key1':'value1'})
  • 表单参数提交: requests.post(url, data={'key1':'value1','key2':'value2'})
  • json 参数提交 requests.post(url, json={'key1':'value1','key2':'value2'})
  • 提交文件 requests.post(url, files={'file':open('sss.csv','rb')})

(3)请求异常处理(异常放在requests.exceptions包内)

  1. 请求超时处理:except exceptions.Timeout
    requests.get(url, timeout=10)
  2. 错误码异常处理 except exceptions.HTTPError
    如果响应的状态码不为200,response.raise_for_status() 会抛出状态码异常:response.raise_for_status()
import requests
from requests.exceptions import Timeout, ConnectionError, RequestException,.HTTPError
 
try:
    resp = requests.get('http://httpbin.org/get', timeout=0.5)
    print(resp.status_code)
except Timeout: # 访问超时的错误
    print('Timeout')
except ConnectionError: # 网络中断连接错误
    print('Connect error')
except RequestException: # 父类错误
    print('Error')
except HTTPError: # 错误码
    print('响应状态非200')

Demo

//伪造头信息
headers = {"Host":" music.163.com",

"User-Agent":" Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0",

}
requests.get(url,headers = headers)

#  文件上传
files = {'file' : open('logo.gif','rb')}
resp = requests.post('http://httpbin.org/post', files=files)

解析响应

1.响应状态码:

1XX:消息

2XX 请求成功:
200 返回响应成功 201 资源建立成功 204 成功响应,无返回  

3XX 重定向:
301 永久移动 302 暂时移动 304 上次的get请求访问过的内容

4XX 客户端错误:
400 请求有问题 401 认证问题 403 权限不足,服务器拒绝执行 404 页面不存在

5XX 服务器端错误:
500 服务器端有bug 501 无法识别请求的方法502 网关错误 503 服务不可用

2. 响应的api

基本api

  • status_code 状态码

  • reason 响应情况

  • headers 获取响应头

  • url( 响应的地址

  • request 获得响应对应的请求的对象,有headers 和 body

内容相关的api:

  • content() 读取二进制内容 常用于图片下载
  • text() 解析为解码后的字符串(可以修改requests.encoding = 'utf-8' 默认是utf-8)
  • json() 将json格式的响应解析为python中的字典

demo

一.图片下载
from contextlib import closing
url = 'http://pic.58pic.com/58pic/16/42/96/56e58PICAu9_1024.jpg'
 #伪造头信息
 headers = {'User-Agent':'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:51.0) 
Gecko/20100101 Firefox/51.0'}
#关闭流的方式发送请求
 with closing(requests.get(url,headers=headers)) as response:
 with open('demo.jpg','wb') as f:
#每128个字节写入一次文件
        for chunk in response.iter_content(128):
            f.write(chunk)

二、事件钩子(Event Hooks) 发送请求,在获取响应时回调钩子函数

import requests
def func(response,*args,**kws):
    pass
requests.get(url,hooks=dict(response=func))

使用进阶

(1) HTTP认证

  1. 基本认证,验证账号与密码
    requests.get(url,auth=(name,password))

  2. OAUTH认证

from requests.auth import AuthBase

class GitHubAuth(AuthBase):
def __init__(self, token):
  self.token= token
def __call__(self,r):
#request 加headers
  r.headers['Authorization'] = '  '.join(['token', self.token])
def oauth_advanced():
  #传入access token
auth = GithubAuth('dddsfsdfsdfasf')
response = requests.get(url,auth = auth)
  1. 代理设置

有些网站会限制 IP 访问频率,超过频率就断开连接。这个时候我们就需要使用到代理,我们可以通过为任意请求方式提供proxies参数来配置单个请求。

import requests
 
proxies = {
    "http": "http://10.10.1.10:3128",
    "https": "http://10.10.1.10:1080",
}
resp = requests.get('http://www.baidu.com', proxies=proxies)
print(resp.status_code)

也可以通过环境变量 HTTP_PROXYHTTPS_PROXY 来配置代理。
有些代理需要加上用户名和密码的,代理可以使用http://user:password@host/语法,比如:

proxies = {
    "http": "http://user:pass@10.10.1.10:3128/",
}

2. xpath的使用

安装

pip install lxml

Demo

from lxml import etree

# 字符串读取html
html_str = '''  
<div>
    <ul>
         <li class="item-0"><a href="link1.html">first item</a></li>
         <li class="item-1"><a href="link2.html">second item</a></li>
         <li class="item-inactive"><a href="link3.html"><span class="bold">third item</span></a></li>
         <li class="item-1"><a href="link4.html">fourth item</a></li>
         <li class="item-0"><a href="link5.html">fifth item</a></li>
     </ul>
 </div>
'''

html = etree.HTML(html_str)
#也可以从文件读取html html = etree.parse('hello.html') 

res = html.xpath("//div/ul/li[@class='item-0']/a")

for e in res:
    print(e.text)
    print(e.get("href"))

xpath语法

1. 获取 <li> 标签的所有 class
result = html.xpath('//li/@class')
print result
运行结果:
['item-0', 'item-1', 'item-inactive', 'item-1', 'item-0']

2. 获取 <li> 标签下 href 为 link1.html 的 <a> 标签
result = html.xpath('//li/a[@href="link1.html"]')
print result
运行结果
[<Element a at 0x10ffaae18>]

3. 获取 <li> 标签下的所有 <span> 标签
不能这样写:result = html.xpath('//li/span')
因为 / 是用来获取子元素的,而 <span> 并不是 <li> 的子元素,所以,要用双斜杠

result = html.xpath('//li//span')
print result
运行结果
[<Element span at 0x10d698e18>]

4. 获取 <li> 标签下的所有 class,不包括 <li>
result = html.xpath('//li/a//@class')
print result
运行结果
['blod']

5. 获取最后一个 <li> 的 <a> 的 href
result = html.xpath('//li[last()]/a/@href')
print result
运行结果
['link5.html']

6. 获取倒数第二个元素的内容
result = html.xpath('//li[last()-1]/a')
print result[0].text
运行结果
fourth item

7. 获取 class 为 bold 的标签名
result = html.xpath('//*[@class="bold"]')
print result[0].tag
运行结果
span

进阶用法

# 对节点进行xpath查询 处理字段缺失
tables = html.xpath("//div[@class='indent']//table")
for table in tables:
            score = table.xpath(".//span[@class='rating_nums']")[0].text
            description = "暂无简介"
            node = table.xpath(".//span[@class='inq']")
            if node:
                description = node[0].text

# 获取某节点内所有文字内容
# <li class="item-1">sss <a href="link2.html">second item</a> ss</li>
res = html.xpath('//li')[1]

text = res.xpath('string(.)')
print(l1)

# 结果: sss second item ss

进阶

MongoDB的使用 设置下载缓存和实现多进程任务

教程

爬虫教程

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,367评论 6 512
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,959评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,750评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,226评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,252评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,975评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,592评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,497评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,027评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,147评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,274评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,953评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,623评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,143评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,260评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,607评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,271评论 2 358

推荐阅读更多精彩内容