Python网络爬虫Requests库和Scrapy库入门


1 Requests库入门

1.1 Requests库安装

pip install requests

Requests库的安装测试:

>>> import requests
>>> r = requests.get("http://www.baidu.com")
>>> r.status_code
200
>>> r.encoding = 'utf-8' #修改默认编码
>>> r.text		#打印网页内容

1.2 HTTP协议

HTTP,Hypertext Transfer Protocol,超文本传输协议

HTTP是一个基于“请求与响应”模式的、无状态的应用层协议。

HTTP协议采用URL作为定位网络资源的标识。

URL格式:http://host[:port][path]

  • host:合法的Internet主机域名或IP地址

  • port:端口号,缺省端口为80

  • path:请求资源的路径

HTTP URL的理解:

URL是通过HTTP协议存取资源的Internet路径,一个URL对应一个数据资源。

HTTP协议对资源的操作:

方法说明
GET请求获取URL位置的资源
HEAD请求获取URl位置资源的响应消息报告,即获得该资源的头部信息
POST请求向URL位置的资源后附加新的数据
PUT请求向URL位置存储一个资源,覆盖原URL位置的资源
PATCH请求局部更新URL位置的资源,即改变该处资源的部分内容
DELETE请求删除URL位置存储的资源

1.3 Requests库方法

方法说明
requests.request()构造一个请求,支撑以下各方法的基础方法
requests.get()获取HTML网页的主要方法,对应于HTTP的GET
requests.head()获取HTML网页头信息的方法,对应于HTTP的HEAD
requests.post()向HTML网页提交POST请求的方法,对应于HTTP的POST
requests.put()向HTML网页提交PUT请求的方法,对应于HTTP的PUT
requests.patch()向HTML网页提交局部修改请求,对应于HTTP的PATCH
requests.delete()向HTML网页提交删除请求,对应于HTTP的DELETE

主要方法为request方法,其余6个都是由request方法封装。

request()方法:

requests.request(method,url,**kwargs)

  • method:请求方式,对应get/put/post等7种
  • url:拟获取页面的url链接
  • **kwargs:控制访问的参数,共13个,均为可选项

13个控制访问参数分别为:

  1. params:字典或字节序列,作为参数增加到url中
  2. data:字典、字节序列或文件对象,作为Request的内容
  3. json:JSON格式的数据,作为Request的内容
  4. headers:字典,HTTP定制头
  5. cookies:字典或CookieJar,Request中的cookie
  6. auth:元祖,支持HTTP认证功能
  7. files:字典类型,传输文件
  8. timeout:设定超时时间,秒为单位
  9. proxies:字典类型,设定访问代理服务器,可以增加登录认证
  10. allow_redirects:True/False,默认为True,重定向开关
  11. stream:True/False,默认为True,获取内容立即下载开关
  12. verify:True/False,默认为True,认证SSL证书开关
  13. cert:本地SSL证书路径

get()方法:

requests.get(url,params=None,**kwargs)

  • url:拟获取页面的url链接
  • params:url中的额外参数,字典或字节流格式,可选
  • **kwargs:12个控制访问的参数

该方法构造了一个向服务器请求资源的Request对象,返回了一个包含服务器资源的Response对象,Response对象包含爬虫返回的内容

Response对象的属性:

属性说明
r.status_codeHTTP请求的返回状态,200表示连接成
r.textHTTP响应内容的字符串形式,即:url对应的页面内容
r.encoding从HTTP header中猜测的响应内容编码方式
r.apparent_encoding从内容中分析出的响应内容编码方式(备选编码方式)
r.contentHTTP响应内容的二进制形式

head()方法:

requests.head(url,**kwargs)

  • url:拟获取页面的url链接
  • **kwargs:13个控制访问的参数

post()方法:

requests.post(url,data=None,json=None,**kwargs)

  • url:拟更新页面的url链接
  • data:字典、字节序列或文件,Request的内容
  • json:JSON格式的数据,Request的内容
  • **kwargs:11个控制访问的参数

put()方法:

requests.put(url,data=None,json=None,**kwargs)

  • url:拟更新页面的url链接
  • data:字典、字节序列或文件,Request的内容
  • **kwargs:12个控制访问的参数

patch()方法:

同put()方法

delet()方法:

requests.delete(url,**kwargs)

  • url:拟删除页面的url链接
  • **kwargs:13个控制访问的参数

1.4 爬取网页的通用代码框架

Requests库的异常:

异常说明
requests.ConnectionError网络连接错误异常,如DNS查询失败、拒绝连接等
requests.HTTPErrorHTTP错误异常
requests.URLRequiredURL缺失异常
requests.TooManyRedirects超过最大 重定向次数,产生重定向异常
requests.ConnectTimeout连接远程服务器超时异常
requests.Timeout请求URL超时,产生超时异常
r.raise_for_status()如果不是200产生异常requests.HTTPError
import requests

def getHTMLText(url):
    try:
        r = requests.get(url,timeout=30)
        r.raise_for_status() #如果不是200,引发HTTPError异常
        r.encoding = r.apparent_encoding
        return r.text
    except:
        return "产生异常"
if __name__ == "__main__":
    url = "http://www.baidu.com"
    print(getHTMLText(url))

1.5 Requests库实战

向360搜索提交关键词:

import requests

# 向搜索引擎进行关键词提交
url = "http://www.so.com/s"
try:
    kv = {'q':'python'}
    r = requests.get(url,params =kv)
    print(r.request.url)
    r.raise_for_status()
    print(len(r.text))
except:
    print("产生异常")

获取网络图片及存储:

import requests
import os
url = "http://image.ngchina.com.cn/2015/0323/20150323111422966.jpg"
root = "D:/pics/"
path = root + url.split('/')[-1]
try:
    if not os.path.exists(root):
        os.mkdir(root)
    if not os.path.exists(path):
        r = requests.get(url)
        with open(path,'wb') as f:
            f.write(r.content)  # r.content返回二进制内容
            f.close()
            print("文件保存成功")
    else:
        print("文件已存在")
except:
    print("爬取失败")

2 Scrapy库入门

2.1 Scrapy库安装

可以用anaconda安装scrapy,打开anaconda prompt,输入以下代码

conda install scrapy

报错:

CondaError: Downloaded bytes did not match Content-Length
  url: https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/win-64/pywin32-227-py37he774522_1.conda
  target_path: E:\Anaconda3\pkgs\pywin32-227-py37he774522_1.conda
  Content-Length: 5808297
  downloaded bytes: 2653872

问题是用conda安装包的时候下载包的长度不够导致安装包不成功,原因一般是在下载的时候速度较慢,通过更新配置的清华镜像源成功解决,具体配置方法请参考:Anaconda 镜像使用帮助

2.2 Scrapy爬虫框架

Scrapy不是一个函数功能库,而是一个爬虫框架。

Scrapy爬虫框架介绍:

  1. 爬虫框架是实现爬虫功能的一个软件结构和功能组件集合。
  2. 爬虫框架是一个半成品,能够帮助用户实现专业网络爬虫。
    在这里插入图片描述

Scrapy爬虫框架解析:

Engine:不需要用户修改

  • 控制所有模块之间的数据流
  • 根据条件触发事件

Downloader:不需要用户修改

  • 根据请求下载网页

Scheduler:不需要用户修改

  • 对所有爬取请求进行调度管理

Downloader Middleware:用户可编写配置代码

  • 目的:实施Engine、Scheduler和Downloader之间进行用户可配置的控制
  • 功能:修改、丢弃、新增请求或响应

Spider:需要用户编写配置代码

  • 解析Downloader返回的响应(Response)
  • 产生爬取项(scraped item)
  • 产生额外的爬取请求(Request)

Item Pipelines:需要用户编写配置代码

  • 以流水线方式处理Spider产生的爬取项
  • 由一组操作顺序组成,类似流水线,每个操作是一个Item Pipeline类型
  • 可能操作包括:清理、检验、和查重爬取项中的HTML数据、将数据存储到数据库

Spider Middleware:用户可以编写配置代码

  • 目的:对请求和爬取项的再处理
  • 功能:修改、丢弃、新增请求或爬取项

2.3 Request库和Scrapy爬虫的比较

requests vs. Scrapy:

相同点:

  • 两者都可以进行页面请求和爬取,Python爬虫的两个重要技术路线
  • 两者可用性都好,文档丰富,入门简单
  • 两者都没有处理js、提交表单、应对验证码等功能(可扩展)

不同点:

requestsScrapy
页面级爬虫网站级爬虫
功能库框架
并发性考虑不足,性能较差并发性好,性能较高
重点在于页面下载重点在于爬虫结构
定制灵活一般定制灵活,深度定制困难
上手十分简单入门稍难

2.4 Scrapy爬虫的常用命令

Scrapy命令行:

Scrapy是为持续运行设计的专业爬虫框架,提供操作的Scrapy命令行

Scrapy常用命令:

命令说明格式
startproject创建一个新工程scrapy startproject <name> [dir]
genspider创建一个爬虫scrapy genspider [options] <name> <domain>
settings获得爬虫配置信息scrapy setting [options]
crawl运行一个爬虫scrapy crawl <spider>
list列出工程中所有爬虫scrapy list
shell启动URL调试命令行scrapy shell [url]

2.5 Scrapy爬虫的第一个实例

步骤1:建立一个Scrapy爬虫工程

打开cmd,输入以下命令在工程目录创建一个新的Scrapy工程,工程名为python123demo
在这里插入图片描述
生成的工程目录:

python123demo/ ----------------> 外层目录

  • scrapy.cfg ---------> 部署Scrapy爬虫的配置文件
  • python123demo/ ---------> Scrapy框架的用户自定义Python代码
    __init__.py ----> 初始化脚本
    items.py ----> Items代码模板(继承类)
    middlewares.py ----> Middlewares代码模板(继承类)
    pipelines.py ----> Pipelines代码模板(继承类)
    settings.py ----> Scrapy爬虫的配置文件

​ spiders/ ----> Spiders代码模板目录(继承类)

  • __init__.py --------> 初始文件,无需修改
  • __pycache__/ --------> 缓存目录,无需修改

步骤2:在工程中产生一个Scrapy爬虫

打开cmd,输入以下命令生成一个名为demo的爬虫
在这里插入图片描述

步骤3:配置产生的spider爬虫

修改D:\pycodes\python123demo\python123demo\spiders\demo.py文件

# -*- coding: utf-8 -*-
import scrapy


class DemoSpider(scrapy.Spider):
    name = 'demo'
#    allowed_domains = ['python123.io']
    start_urls = ['http://python123.io/ws/demo.html']

    def parse(self, response):
        fname = response.url.split('/')[-1]
        with open(fname, 'wb') as f:
            f.write(response.body)
        self.log('Save file %s.' % name)

demo.py代码的完整版本

import scrapy

class DemoSpider(scrapy.Spider):
    name = "demo"
    
    def start_requests(self):
        urls = [
        		'http://python123.io/ws/demo.html'
        		]
        for url in urls:
            yield scrapy.Requests(url=url, callback=self.parse)
            
    def parse(self, response):
        fname = response.url.split('/')[-1]
        with open(fname, 'wb') as f:
            f.write(response.body)
        self.log('Saved file %s.' % fname)

步骤4:运行爬虫,获取网页

打开cmd,输入以下命令运行爬虫
在这里插入图片描述

2.6 Scrapy爬虫的基本使用

Scrapy爬虫的使用步骤:

  • 步骤1:创建一个工程和Spider模板;
  • 步骤2:编写Spider;
  • 步骤3:编写Item Pipeline
  • 步骤4:优化配置策略

2.7 Scrapy爬虫的数据类型

Request类:

class scrapy.http.Request()

  • Request对象表示一个HTTP请求
  • 由Spider生成,由Downloader执行
属性或方法说明
.urlRequest对应的请求URL地址
.method对应的请求方法,’GET‘ ’POST‘等
.headers字典类型风格的请求头
.body请求内容主体,字符串类型
.meta用户添加的扩展信息,在Scrapy内部模块间传递信息使用
.copy()复制该请求

Response类:

class scrapy.http.Response()

  • Response对象表示一个HTTP响应
  • 由Downloader生成,由Spider处理
属性或方法说明
.urlResponse对应的URL地址
.statusHTTP状态码,默认是200
.headersResponse对应的头部信息
.bodyResponse对应的内容信息,字符串类型
.flags一组标记
.request产生Response类型对应的Request对象
.copy()复制该响应

Item类:

class scrapy.item.Item()

  • Item对象表示一个从HTML页面中提取的信息内容
  • 由Spider生成,由Item Pipeline处理
  • Item类似字典类型,可以按照字典类型操作

2.8 Scrapy爬虫提取信息的方法

Scrapy爬虫支持多种HTML信息提取方法:

  • Beautiful Soup
  • lxml
  • re
  • XPath Selector
  • CSS Selector

CSS Selector的基本使用:
在这里插入图片描述
CSS Selector由W3C组织维护并规范

2.9 股票数据Scrapy爬虫实例

功能描述:

  • 技术路线:scrapy
  • 目标:获取上交所和深交所所有股票的名称和交易信息
  • 输出:保存到文件中

步骤1:建立工程和Spider模板

  • \>scrapy startproject BaiduStocks
  • \>cd BaiduStocks
  • \>scrapy genspider stocks baidu.com
  • 进一步修改spiders/stocks.py文件

步骤2:编写Spider

  • 配置stock.py文件
  • 修改对返回页面的处理
  • 修改对新增URL爬取请求的处理

修改spider.stocks.py文件使其能够解析返回的信息

# -*- coding: utf-8 -*-
import scrapy
import re
    
    
class StocksSpider(scrapy.Spider):
    name = "stocks"
    start_urls = ['https://quote.eastmoney.com/stocklist.html']
    
    def parse(self, response):
        for href in response.css('a::attr(href)').extract():
            try:
                stock = re.findall(r"[s][hz]\d{6}", href)[0]
                url = 'https://gupiao.baidu.com/stock/' + stock + '.html'
                yield scrapy.Request(url, callback=self.parse_stock)
            except:
                continue
    
    def parse_stock(self, response):
        infoDict = {}
        stockInfo = response.css('.stock-bets')
        name = stockInfo.css('.bets-name').extract()[0]
        keyList = stockInfo.css('dt').extract()
        valueList = stockInfo.css('dd').extract()
        for i in range(len(keyList)):
            key = re.findall(r'>.*</dt>', keyList[i])[0][1:-5]
            try:
                val = re.findall(r'\d+\.?.*</dd>', valueList[i])[0][0:-5]
            except:
                val = '--'
            infoDict[key]=val
    
        infoDict.update(
            {'股票名称': re.findall('\s.*\(',name)[0].split()[0] + \
                re.findall('\>.*\<', name)[0][1:-1]})
        yield infoDict

步骤3:编写Pipelines

  • 配置pipelines.py文件
  • 定义对爬取项(Scrapy Item)的处理类
  • 配置ITEM_PIPELINES选项

修改pipelines.py

# -*- coding: utf-8 -*-
    
# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html
    
    
class BaidustocksPipeline(object):
    def process_item(self, item, spider):
        return item
    
class BaidustocksInfoPipeline(object):
    def open_spider(self, spider):
        self.f = open('BaiduStockInfo.txt', 'w')
    
    def close_spider(self, spider):
        self.f.close()
    
    def process_item(self, item, spider):
        try:
            line = str(dict(item)) + '\n'
            self.f.write(line)
        except:
            pass
        return item

修改setting.py中的ITEM_PIPELINES使框架能找到我们新定义的类

# Configure item pipelines
# See https://scrapy.readthedocs.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
	'BaiduStocks.pipelines.BaidustocksInfoPipeline': 300,
}

配置并发连接选项:

settings.py文件

选项说明
CONCURRENT_REQUESTSDownloader最大并发请求下载数量,默认为32
CONCURRENT_ITEMSItem Pipeline最大并发ITEM处理数量,默认为100
CONCURRENT_REQUESTS_PRE_DOMAIN每个目标域名最大的并发请求数量,默认为8
CONCURRENT_REQUESTS_PRE_IP每个目标IP最大的并发请求数量,默认为0,非0有效
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值