twisted介绍
Twisted是用Python实现的基于事件驱动的网络引擎框架,scrapy正是依赖于twisted,
它是基于事件循环的异步非阻塞网络框架,可以实现爬虫的并发。
twisted是什么以及和requests的区别:
- request是一个python实现的可以伪造浏览器发送Http请求的模块,它封装了socket发送请求
- twisted是基于时间循环的异步非阻塞的网络框架,它也封装了socket发送请求,但是他可以单线程的完成并发请求。
twisted的特点是:
- 非阻塞:不等待
- 异步:回调
- 事件循环:一直循环去检查状态
scrapy的pipeline文件和items文件
这两个文件有什么作用
先看看我们上篇的示例:
# -*- coding: utf-8 -*-
import
scrapy
class
ChoutiSpider(scrapy.Spider):
‘‘‘
爬去抽屉网的帖子信息
‘‘‘
name
=
‘chouti‘
allowed_domains
=
[
‘chouti.com‘
]
start_urls
=
[
‘http://chouti.com/‘
]
def
parse(
self
, response):
# 获取帖子列表的父级div
content_div
=
response.xpath(
‘//div[@id="content-list"]‘
)
# 获取帖子item的列表
items_list
=
content_div.xpath(
‘.//div[@class="item"]‘
)
# 打开一个文件句柄,目的是为了将获取的东西写入文件
with
open
(
‘articles.log‘
,
‘a+‘
,encoding
=
‘utf-8‘
) as f:
# 循环item_list
for
item
in
items_list:
# 获取每个item的第一个a标签的文本和url链接
text
=
item.xpath(
‘.//a/text()‘
).extract_first()
href
=
item.xpath(
‘.//a/@href‘
).extract_first()
# print(href, text.strip())
# print(‘-‘*100)
f.write(href
+
‘\n‘
)
f.write(text.strip()
+
‘\n‘
)
f.write(
‘-‘
*
100
+
‘\n‘
)
# 获取分页的页码,然后让程序循环爬去每个链接
# 页码标签对象列表
page_list
=
response.xpath(
‘//div[@id="dig_lcpage"]‘
)
# 循环列表
for
page
in
page_list:
# 获取每个标签下的a标签的url,即每页的链接
page_a_url
=
page.xpath(
‘.//a/@href‘
).extract()
# 将域名和url拼接起来
page_url
=
‘https://dig.chouti.com‘
+
page_a_url
# 重要的一步!!!!
# 导入Request模块,然后实例化一个Request对象,然后yield它
# 就会自动执行Request对象的callback方法,爬去的是url参数中的链接
from
scrapy.http
import
Request
yield
Request(url
=
page_url,callback
=
self
.parse)
在这个示例中,虽然我们已经通过chouti.py一个文件中的parse方法实现了爬去抽屉网的新闻并将之保存在文件中的功能,
但是我们会发现有两个问题:
1、在循环爬去每一页的时候,每次都需要重新打开然后再关闭文件,如果数据量庞大的话,这对性能有很大的影响。
2、我们将解析和数据持久化都放在了同一个文件的同一个方法中,没有做到分工明确
如果要解决这两个问题,则需要用到scrapy自动为我们生成的pipeline文件和items文件
这两个文件怎么用
如果我们要使用这两个文件从而解决问题,则需要有四部操作:
a.编写pipeline文件中的类,格式如下:
1 2 3 |
|
b.编写items文件中的类,格式如下:
1 2 3 |
|
c.配置settings文件
1 2 3 4 |
|
d.在parse方法中yield一个Item对象
1 2 3 4 5 |
|
执行流程为:
当我们在执行爬虫中的parse方法的时候,scrapy一旦解析到有yield XXXitem的语句,就会到配置文件中找
ITEM_PIPELINES的配置项,进而找到XXXPipeline类,然后执行其中的方法,我们就可以在方法中做很多操作
当然,pipeline中不止process_item一个方法。
Pipeline中的方法详解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
|
去重
scrapy内部实现的去重
从上一篇的例子我们可以看出,其实scrapy内部在循环爬去页码的时候,已经帮我们做了去重功能的,
因为我们在首页可以看到1,2,3,4,5,6,7,8,9,10页的页码以及连接,当爬虫爬到第二页的时候,
还是可以看到这10个页面及连接,然后它并没有再重新把第一页爬一遍。
它内部实现去重的原理是,将已爬去的网址存入一个set集合里,每次爬取新页面的时候就先看一下是否在集合里面
如果在,就不再爬去,如果不在就爬取,然后再添加入到set里。当然,这个集合存放的不是原网址,
而是将链接通过request_fingerprint()方法将它变成一个类似于md5的值,这样可以节省存储空间
自定义去重
虽然scrapy已经帮我们实现了去重,但是有时候不足以满足我们的需求,这样就需要我们自定义去重了
自定义去重分两步
1、编写DupeFilter类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
|
2.配置settings文件
1 2 3 |
|
深度
深度就是爬虫所要爬取的层级
限制深度只需要配置一下即可
1 2 |
|
cookie
获取上一次请求之后获得的cookie
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
再次请求的时候携带cookie
1 2 3 4 5 6 7 8 9 10 |
|
是不是感觉很麻烦?
那么,呵呵,其实,嘿嘿,
你只需要在Request对象的参数中加入 meta={‘cookiejar‘: True} 即可!
网络爬虫之scrapy框架设置代理
前戏
os.environ()简介
os.environ()可以获取到当前进程的环境变量,注意,是当前进程。
如果我们在一个程序中设置了环境变量,另一个程序是无法获取设置的那个变量的。
环境变量是以一个字典的形式存在的,可以用字典的方法来取值或者设置值。
os.environ() key字段详解
windows:
1 2 3 4 5 6 |
|
linux:
1 2 3 4 5 |
|
内置的方式
原理
scrapy框架内部已经实现了设置代理的方法,它的原理是从环境变量中取出设置的代理,然后再使用,
所以我们只需要在程序执行前将代理以键值对的方式设置到环境变量中即可。
代码
第一种方式:直接添加键值对的方式
1 2 3 4 5 6 7 8 9 10 11 12 |
|
第二种方式:设置meta参数的方式
1 2 3 4 5 6 7 8 9 |
|
自定义方式
原理
我们可以根据内部实现的添加代理的类(中间件)的实现方法,来对它进行升级,比如内部的方式一次只能使用一个代理,
我们可以弄一个列表,装很多代理地址,然后随机选取一个代理,这样可以防止请求过多被封ip
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
|
写完类之后需要在settings文件里配置一下:
1 2 3 |
|
原文地址:https://www.cnblogs.com/xyhh/p/10860873.html