资讯详情

网络爬虫开发

01 网络爬虫改善

1.1 一般网络的基本工作流程如图所示:

1.2 网络爬虫的基本工作流程如下:

  1. 获取出生的URL,该URL地址是用户自己制定的初始爬网页;
  2. 爬取对应URL获取地址网页时,获取新的网页URL地址;
  3. 将新的URL地址放入URL队列中;
  4. 从URL在队列中读取新的URL,然后根据新的URL爬网页,从新网页中获取新网页URL重复上述爬行过程;
  5. 设置停止条件。如果没有停止条件,爬虫会一直爬下去,直到得不到新的URL地址位置。在设置停止条件后,爬虫将在满足停止条件时停止爬行。

02 常用的网络爬虫技术

2.1 Python的网络请求

Python中实现HTTP三种常见的网络请求方式:urbbib、urllib3、requests;

2.1.1 urllib模块

urllib是python该模块提供了自己的模块urlopen()制定方法URL发送网络请求获取数据。urllib具体的模块名称和含义如下表所示:

模块名称 描述
urbbib.request 该模块定义了打开URL(主要是HTTP)身份验证、重定向、cookie等
urbbib.error 该模块主要包含异常类,基本的异常类是URLError
urbbib.parse 该模块定义的功能分为两类:URL解析和URL引用
urbbib 该模块用于分析robot.txt文件

通过urllib.request模块

import urllib.request      #导入模块 #打开需要爬行的指定网页 response = urllib.request.urlopen('http://www.baidu.com')         html = response.read()     #阅读网页代码 print(html)                #打印读取内容

上面的例子是通过的get请求获取百度网页内容;

使用下面urllib.request模块的post请求实现获取网页信息的内容,示例如下:

import urllib.parse import urllib.request  #使用数据urlencode编码后再使用encoding设置魏utf-8编码 data =bytes(urllib.parse.urlencode({'word':'hello'}),encoding ='utf-8') #打开指定需要爬行的网页 response = urllib.request.urlopen('http://httpbin.org/post',data = data) html = response.read()    #阅读网页代码 print(html)               #打印读取内容

2.2 Urllib3模块

Urllib三是功能强大,组织清晰,用于HTTP客户端的Python库,许多Python原生系统已经开始使用Urllib3。Urllib3提供了很多Python标准库中没有的重要特征:

  • 线程安全;
  • 连接池;
  • 客户端SSL/TLS验证;
  • 使用大部分编码上传文件;
  • helpers用于重试请求和处理HTTP重定向;
  • 指出gzip和deflate编码;
  • 指出HTTP和SOCKS带来;
  • 测试覆盖率100%;

2.3 requests 模块

requests是python中实现HTTP请求的一种方式,requests该模块是实现的第三方模块HTTP请求时要比urllib模块简化多,操作更人性化。在使用中requests需要执行模块pip install requests安装该模块的代码。requests模块的功能特性如下:

  • Keep-Alive&连接池
  • 国际域名和URL
  • 带持久Cookie的会话
  • 浏览器式的SSL认证
  • 解码自动内容
  • 基本/摘要式身份认证
  • 优雅的key/value Cookie
  • 自动解压
  • 流下载
  • 连接超时
  • Unicode响应体
  • HTTP(S)代理支持
  • 分块上传文件
  • 分块请求
  • 支持 .netrc

import requests response = requests.get('http://www.baidu.com') print(response.status_code)          #打印状态码 print(response.url)                  #打印请求url  print(response.headers)              #打印头部信息 print(response.cookies)              #打印cookie信息 print(response.text)                 #以文本形式打印网页源码 print(response.content)              #以字节流的形式打印网页源码

以POST请求方式,发送HTTP网络请求示例代码如下:

import requests data = {'word':'hello'}       #表单参数 #向需要爬行的网页发送请求 response = requests.post('http://httpbin.org/post',data = data) print(response.content)      #以字节流的形式打印网页源码

request该模块不仅提供了上述两种常用的请求方式,还提供了以下网络请求方式。代码如下:

import requests print(requests.put('http://httpbin.org/put',data={'key':'value'}))  #PUT请求 print(requests.delete('http://httpbin.org/delete'))                #DELETE请求 print(requests.head('http://httpbin.org/get'))                     #HEAD请求 print(requests.options('http://httpbin.org/get'))                   #OPTTIONS请求

这些代码输出如下:

<Response [200]> <Response [200]> <Response [200]> <Response [200]>

若发现请求URL跟随地址中的参数"?"后面,比如"httpbin.org/get?key=val"

requests允许模块提供访问传输参数的方法params用字符串字典提供关键字参数。

例如,传递“key1=value1”和“key2=value2”到“heepbin,org/get可使用以下代码:

import  requests payload={'key1':'value1','key2':'vulue2'} #向需要爬行的网页发送请求 response = requests.get("http://httpbin.org/get",params=payload) print(response.content)

这些代码输出如下:

b'{\n "args": {\n "key1": "value1", \n "key2": "vulue2"\n }, \n "headers": {\n "Accept": "*/*", \n "Accept-Encoding": "gzip, deflate", \n "Host": "httpbin.org", \n "User-Agent": "pyton-requests/2.28.1", \n    "X-Amzn-Trace-Id": "Root=1-62ce41e8-1381febe782bab3b5ecf4dcb"\n  }, \n  "origin": "115.196.88.185", \n  "url": "http://httpbin.org/get?key1=value1&key2=vulue2"\n}\n'

2.2 请求headers处理

  • 有时在请求一个网页内容时,发现无论通过GET或者是POST以及其他请求方式,都会出现403错误;
  • 产生这种错误是由于该网页为了防止恶意采集信息而使用了反爬虫设置,从而拒绝了用户的访问;
  • 此时可以通过模拟浏览器的头部信息来进行访问,这样就能解决以上反爬设置的问题;
  • 下面以requests模块为例介绍请求头部headers的处理,具体步骤如下:

通过浏览器的网络解释器查看头部信息,首先通过浏览器打开对应的网页地址,然后按下F12打开网络监视器,再刷新当前页面,

选中第一条信息,右侧的消息头面板中将显示请求头部信息绵软后复制该信息,如下所示:

实现代码。首先创建一个需要爬取的url地址,然后创建header头部信息,在发送请求等待响应,最后打印网页的代码信息。代码实现如下:

import requests
url = 'https://www.baidu.com/'    #创建需要爬取网页的地址
#创建header头部信息
headers = {'User-Agent':'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Mobile Safari/537.36'}
response = requests.get(url,headers=headers)    #发送网络请求
print(response.content)                         #以字节流形式打印网络源码

2.3 网络超时

在访问一个网页时,如果该网页长时间未响应,系统就会判断网页超时,所以无法打开网页。

下面通过代码来模拟一个网络超时的现象,代码如下:

200 异常HTTPConnectionPool(host='www.baidu.com', port=80): Read timed out. (read timeout=0.01) 200 异常HTTPConnectionPool(host='www.baidu.com', port=80): Read timed out. (read timeout=0.01) 200 200 异常HTTPConnectionPool(host='www.baidu.com', port=80): Read timed out. (read timeout=0.01) 200 异常HTTPConnectionPool(host='www.baidu.com', port=80): Read timed out. (read timeout=0.01) 200 200 异常HTTPConnectionPool(host='www.baidu.com', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000002597F6EB550>, 'Connection to www.baidu.com timed out. (connect timeout=0.01)')) 200 异常HTTPConnectionPool(host='www.baidu.com', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000002597F744040>, 'Connection to www.baidu.com timed out. (connect timeout=0.01)')) 异常HTTPConnectionPool(host='www.baidu.com', port=80): Read timed out. (read timeout=0.01) 异常HTTPConnectionPool(host='www.baidu.com', port=80): Read timed out. (read timeout=0.01) 异常HTTPConnectionPool(host='www.baidu.com', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000002597F6EA890>, 'Connection to www.baidu.com timed out. (connect timeout=0.01)')) 200 200 异常HTTPConnectionPool(host='www.baidu.com', port=80): Read timed out. (read timeout=0.01) 异常HTTPConnectionPool(host='www.baidu.com', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000002597F744730>, 'Connection to www.baidu.com timed out. (connect timeout=0.01)')) 异常HTTPConnectionPool(host='www.baidu.com', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000002597F6EAD40>, 'Connection to www.baidu.com timed out. (connect timeout=0.01)')) 异常HTTPConnectionPool(host='www.baidu.com', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000002597F6EBCA0>, 'Connection to www.baidu.com timed out. (connect timeout=0.01)')) 200 异常HTTPConnectionPool(host='www.baidu.com', port=80): Read timed out. (read timeout=0.01) 异常HTTPConnectionPool(host='www.baidu.com', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000002597F6EBA90>, 'Connection to www.baidu.com timed out. (connect timeout=0.01)')) 异常HTTPConnectionPool(host='www.baidu.com', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000002597F6EB010>, 'Connection to www.baidu.com timed out. (connect timeout=0.01)')) 200 异常HTTPConnectionPool(host='www.baidu.com', port=80): Read timed out. (read timeout=0.01) 200 异常HTTPConnectionPool(host='www.baidu.com', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000002597F6EB6D0>, 'Connection to www.baidu.com timed out. (connect timeout=0.01)')) 200 异常HTTPConnectionPool(host='www.baidu.com', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000002597F6EAB60>, 'Connection to www.baidu.com timed out. (connect timeout=0.01)')) 异常HTTPConnectionPool(host='www.baidu.com', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000002597F6A68F0>, 'Connection to www.baidu.com timed out. (connect timeout=0.01)')) 异常HTTPConnectionPool(host='www.baidu.com', port=80): Read timed out. (read timeout=0.01) 200 异常HTTPConnectionPool(host='www.baidu.com', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000002597F6EA290>, 'Connection to www.baidu.com timed out. (connect timeout=0.01)')) 异常HTTPConnectionPool(host='www.baidu.com', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000002597F6EB760>, 'Connection to www.baidu.com timed out. (connect timeout=0.01)')) 200 异常HTTPConnectionPool(host='www.baidu.com', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000002597F6E95D0>, 'Connection to www.baidu.com timed out. (connect timeout=0.01)')) 异常HTTPConnectionPool(host='www.baidu.com', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000002597F744760>, 'Connection to www.baidu.com timed out. (connect timeout=0.01)')) 异常HTTPConnectionPool(host='www.baidu.com', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000002597F744CA0>, 'Connection to www.baidu.com timed out. (connect timeout=0.01)')) 异常HTTPConnectionPool(host='www.baidu.com', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000002597F6EB6A0>, 'Connection to www.baidu.com timed out. (connect timeout=0.01)')) 异常HTTPConnectionPool(host='www.baidu.com', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000002597F6EA440>, 'Connection to www.baidu.com timed out. (connect timeout=0.01)')) 异常HTTPConnectionPool(host='www.baidu.com', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000002597F6EB790>, 'Connection to www.baidu.com timed out. (connect timeout=0.01)')) 异常HTTPConnectionPool(host='www.baidu.com', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000002597F6EA800>, 'Connection to www.baidu.com timed out. (connect timeout=0.01)')) 异常HTTPConnectionPool(host='www.baidu.com', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000002597F744EE0>, 'Connection to www.baidu.com timed out. (connect timeout=0.01)')) 异常HTTPConnectionPool(host='www.baidu.com', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000002597F7443D0>, 'Connection to www.baidu.com timed out. (connect timeout=0.01)')) 异常HTTPConnectionPool(host='www.baidu.com', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000002597F6EA650>, 'Connection to www.baidu.com timed out. (connect timeout=0.01)')) 异常HTTPConnectionPool(host='www.baidu.com', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000002597F6EA0B0>, 'Connection to www.baidu.com timed out. (connect timeout=0.01)'))

说明:上面的代码中,模拟进行了50次循环请求,并且设置了超时的时间为0.01秒,所以在0.01秒内服务器未作出响应将视为超时,所以将超时信息打印在控制台中。

说起网络异常信息,requests模块同样提供了3种常见的网络异常类型,示例代码如下:

import requests
#导入requests.exceptions模块中的3中异常
from requests.exceptions import ReadTimeout,HTTPError,RequestException
#循环发送请求50次
for a in range(0,50):
    try:
        #设置超时未0.5秒
        response = requests.get("https://www.baidu.com/",timeout=0.02)
        print(response.status_code)    #d打印状态码
    except ReadTimeout:      #超时异常
        print('timeout')
    except HTTPError:        #HTTP异常
        print('httperror')
    except RequestException:  #请求异常
        print('reqerror')


timeout timeout timeout timeout timeout timeout timeout timeout 200 timeout timeout 200 timeout timeout timeout timeout timeout timeout timeout timeout timeout timeout reqerror reqerror timeout timeout timeout timeout reqerror timeout timeout timeout timeout 200 timeout timeout timeout timeout timeout reqerror reqerror timeout reqerror reqerror timeout timeout timeout timeout timeout timeout

2.4 代理服务

  • 再爬取网页的过程中,经常会出现不久前可以爬取的网页现在无法爬取了,这是因为你的IP被爬取网址的服务器屏蔽了。
  • 此次代码服务可以为你解决这一麻烦,设置代理时,首先需要找到代理地址,例如122.144.31.177,对应的端口号为808,完整的格式为122.144.31.177:808;
  • 代码示例如下:
import requests
proxy = {'http':'122.114.31.177:888','https':'122.114.31.177:8080'}
#对需要爬取的网页发送请求
response = requests.get('http://www.wingrisoft.com/',proxies=proxy)
print(response.content)

由于示例中代理的IP是免费的,所以使用的时间不固定,超出使用的时间范围内该地址将失效。在地址失效或者地址错误后,控制台将显示如下报错:

TimeoutError

2.5 HTML解析之Beautiful Soup

  • Beautiful Soup是一个用于从HTML和XML文件中提取数据的python库。Beautiful Soup提供一些简单的函数用来处理导航、搜索、修改分析树等功能。Beautiful Soup模块中的查找功能非常强大,而且非常便捷,它通常节省程序员大量的工作时间。
  • Beautiful Soup自动将输入文档转化为Unicode编码,输出文档转化为UTF-8编码。你不需要考虑编码方式,除非文档没有指定一个编码方式,此时Beautiful Soup就不能自动识别编码方式了。然后你需要说明一下原始编码方式就可以了。

Beautiful Soup支持python标准库中包含的HTML解析器,但它也支持许多第三方python解析器,其中

3 网络爬虫开发的常用框架

3.1 Scrapy爬虫框架

  • Scrapy框架是一套比较成熟的Python爬虫框架,简单轻巧,并且非常方便,可以高效率的爬取Web页面并从页面中提取结构化的数据。
  • Scrapy是一套开源的框架,所以在使用时不需要担心收取费用的问题。
  • Scrapy的官方网址为:https://scary.org

3.2 Crawley爬虫框架

Crawley也是python开发出的爬虫框架,该框架致力于改变人们从互联网中提取数据的方式。

Crawley的具体特征如下:

  • 基于Eventlet构建的高速网络爬虫框架;
  • 可以将数据存储在关系型数据库中,如Postgres、Mysql、Oracle、SQLite等数据库;
  • 可以将爬取的数据导入为Json,XML格式;
  • 支持非关系数据库,例如Mongdb和Couchdb;
  • 支持命令行工具;
  • 可以使用你喜欢的工具进行数据的提取,例如XPath或Pyquery工具;
  • 支持使用Cookie登录或访问哪些只有登录才可以访问的网页;
  • 简单易学;

3.3 PySpider爬虫框架

相对于Scrapy框架而言,PySpider框架还是新秀。PySpider框架采用python语言编写,分布式架构,支持多种数据库后端,强大的webUI支持脚本浏览器,任务监视器,项目管理器以及结果查看器。PySpider框架的具体特性如下:

  • Python脚本控制,可以用任何你喜欢的HTML解析包(内置pyquery);
  • WEB界面编写调试脚本、起停脚本、监控执行状态、查看活动历史、回去结果产出;
  • 支持RabbitMQ、Beanstalk、Redis个Kombu作为消息队列;
  • 支持爬取JavaScript页面;
  • 强大的调度控制,支持超时重爬及优先级设置;
  • 组件可替换,支持单机/分布式部署,支持Docker部署;

4 实战项目:快手爬票

4.1 快手爬票概述

4.2 搭建QT环境

标签: dcb连接器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台