递归解析

糗事百科递归解析

在前面的例子里只是爬取了糗事百科热门的第一个页面,但是当我们需要爬取更多的页面时,需要对每个页面的url依次发起请求,然后通过解析的方法进行作者和标题的解析。

我们可以构建一个url列表,放进去所有页面的url,但是这样是不推荐的。

我们也可以通过requests的方法来手动解析,然后来使用递归的思想来编写程序。

比如:

糗事百科首页的页码

# -*- coding: utf-8 -*-
import scrapy
from happy.items import HappyItem class QiushiSpider(scrapy.Spider):
name = 'qiushi'
allowed_domains = ['www.qiushibaike.com']
start_urls = ['http://www.qiushibaike.com/']
# 爬取多个页面
pageNum = 1
url = 'https://www.qiushibaike.com/8hr/page/%d/' def parse(self, response):
# xpath为response中的方法
odiv = response.xpath('//div[@class="recommend-article"]//li')
for li in odiv:
# 连续的li里面混有广告,屏蔽掉广告
try:
title = li.xpath('.//div[@class="recmd-right"]/a/text()')[0].extract()
author = li.xpath('.//span[@class="recmd-name"]/text()')[0].extract()
except:
continue
# 提供item到管道文件
item = HappyItem()
item['title'] = title
item['author'] = author
yield item
# 爬取所有页码数据
if self.pageNum <= 13:
self.pageNum += 1
url = self.url%(self.pageNum)
# 递归爬取数据 发起URL请后,将得到的数据进行使用parse解析,所以要使用回调函数callback
yield scrapy.Request(url=url, callback=self.parse)

得到结果:

post请求发送

Scrapy不用手动对起始列表中的url发送请求,是因为爬虫文件中爬虫类继承了Spider父类中start_requests(self)方法,该方法就可以对初始列表中的url发起请求。

  def start_requests(self):
for u in self.start_urls:
yield scrapy.Request(url=u,callback=self.parse)

但是该方法默认实现的是get请求,如果需要发起post请求,则需要子类重写该方法

def start_requests(self):
#请求的url
post_url = 'http://fanyi.baidu.com/sug'
# post请求参数
formdata = {
'kw': 'wolf',
}
# 发送post请求
yield scrapy.FormRequest(url=post_url, formdata=formdata, callback=self.parse)

Scrapy的日志等级

在使用Scrapy crawl spidername 运行程序时,在终端里打印输出的就是Scrapy的日志。

一般的日志种类:

  ERROR:错误

  WARNING:警告

  INFO:一般的信息

  DEBUG:调试的信息

设置日志的指定输出:

在settings.py配置文件中加入:

  LOG_LEVEL = 日志的指定种类

  LOG_FILE = ‘log.txt’ 表示将日志写入指定文件

请求传参

有时候我们爬取的数据不在同一个页面,比如在这个页面的下级页面,这时候我们就需要用法请求传参。

例子:https://www.cnblogs.com/xiaozx/p/10744604.html 爬取网易新闻的国内版 srapy

提高scrapy爬取效率的技巧

1 增加并发:

默认scrapy开启的并发线程为32个,可以适当进行增加。在settings配置文件中修改CONCURRENT_REQUESTS = 100值为100,并发设置成了为100。

2  降低日志级别:

在运行scrapy时,会有大量日志信息的输出,为了减少CPU的使用率。可以设置log输出信息为INFO或者ERROR即可。在配置文件中编写:LOG_LEVEL = ‘INFO’.

3 禁止cookie

如果不是真的需要cookie,则在scrapy爬取数据时可以进制cookie从而减少CPU的使用率,提升爬取效率。在配置文件中编写:COOKIES_ENABLED = False.

4 禁止重试

对失败的HTTP进行重新请求(重试)会减慢爬取速度,因此可以禁止重试。在配置文件中编写:RETRY_ENABLED = False.

5 减少下载超时

如果对一个非常慢的链接进行爬取,减少下载超时可以能让卡住的链接快速被放弃,从而提升效率。在配置文件中进行编写:DOWNLOAD_TIMEOUT = 10 超时时间为10s.

示例

爬取校花网校花图片 www.521609.com

# -*- coding: utf-8 -*-
import scrapy
from xiaohua.items import XiaohuaItem class XiahuaSpider(scrapy.Spider): name = 'xiaohua'
allowed_domains = ['www.521609.com']
start_urls = ['http://www.521609.com/daxuemeinv/'] pageNum = 1
url = 'http://www.521609.com/daxuemeinv/list8%d.html' def parse(self, response):
li_list = response.xpath('//div[@class="index_img list_center"]/ul/li')
for li in li_list:
school = li.xpath('./a/img/@alt').extract_first()
img_url = li.xpath('./a/img/@src').extract_first() item = XiaohuaItem()
item['school'] = school
item['img_url'] = 'http://www.521609.com' + img_url yield item if self.pageNum < 10:
self.pageNum += 1
url = format(self.url % self.pageNum)
#print(url)
yield scrapy.Request(url=url,callback=self.parse)

pipelines.py

import json
import os
import urllib.request
class XiaohuaPipeline(object):
def __init__(self):
self.fp = None def open_spider(self,spider):
print('开始爬虫')
self.fp = open('./xiaohua.txt','w') def download_img(self,item):
url = item['img_url']
fileName = item['school']+'.jpg'
if not os.path.exists('./xiaohualib'):
os.mkdir('./xiaohualib')
filepath = os.path.join('./xiaohualib',fileName)
urllib.request.urlretrieve(url,filepath)
print(fileName+"下载成功") def process_item(self, item, spider):
obj = dict(item)
json_str = json.dumps(obj,ensure_ascii=False)
self.fp.write(json_str+'\n') #下载图片
self.download_img(item)
return item def close_spider(self,spider):
print('结束爬虫')
self.fp.close()

重点是settings.py 设置有利于爬虫下载的方式

USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'

# Obey robots.txt rules
ROBOTSTXT_OBEY = False # Configure maximum concurrent requests performed by Scrapy (default: 16)
CONCURRENT_REQUESTS = 100
COOKIES_ENABLED = False
LOG_LEVEL = 'ERROR'
RETRY_ENABLED = False
DOWNLOAD_TIMEOUT = 3
# Configure a delay for requests for the same website (default: 0)
# See https://doc.scrapy.org/en/latest/topics/settings.html#download-delay
# See also autothrottle settings and docs
# The download delay setting will honor only one of:
#CONCURRENT_REQUESTS_PER_DOMAIN = 16
#CONCURRENT_REQUESTS_PER_IP = 16
DOWNLOAD_DELAY = 3

UA池和代理池

下载中间件

下载中间件,是位于引擎和下载器之间的一组层组件。

作用:

1 引擎将请求传递给下载器的过程中,下载中间件可以对请求进行一些列的处理,比如设置user-agent,设置代理等。

2 在下载器完成将response传递给引擎中,下载中间件可以对响应进行一些列处理,比如进行gzip解压等。

我们使用下载中间件,一般会对请求随机的设置user-agent,设置随机的代理,目的在于应对网站的反爬策略。

ua池

尽可能多将scrapy工程的请求伪装成不同类型的浏览器身份。

流程:

1 在下载中间件中拦截请求

2 将拦截到的请求信息中的UA进行篡改

3 在配置文件中开启下载中间件

import random
from scrapy.contrib.downloadermiddleware.useragent import UserAgentMiddleware # 单独给ua池一个下载中间件的一个类
class RandomUserAgent(UserAgentMiddleware): def process_request(self, request, spider):
user_agent_list = [
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 "
"(KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1",
"Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 "
"(KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 "
"(KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 "
"(KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6",
"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 "
"(KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 "
"(KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5",
"Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 "
"(KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 "
"(KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 "
"(KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 "
"(KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 "
"(KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 "
"(KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 "
"(KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 "
"(KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 "
"(KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 "
"(KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 "
"(KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24",
"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 "
"(KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24"
]
# 随机挑选一个user-agent
ua = random.choice(user_agent_list)
# 将他写入到当前拦截到的request请求中
request.headers.setdefault('User-Agent', ua)

settings.py

DOWNLOADER_MIDDLEWARES = {
'happy2.middlewares.RandomUserAgentMiddleware': 400,
}
代理池

尽可能多将scrapy工程的请求设置成不同的ip访问。

流程:

1 在下载中间件中拦截请求

2 将拦截到的请求ip改成某一代理ip

3 在配置文件中开启下载中间件

# 还是单独写一个类
class ProxyMiddleware(object): def process_request(self, request, spider):
# http型的可用ip
PROXY_http = [
'153.180.102.104:80',
'195.208.131.189:56055',
]
# 这是https请求类型的可用IP
PROXY_https = [
'120.83.49.90:9000',
'95.189.112.214:35508',
]
# 取出本次请求的路径
h = request.url.split(':')[0]
if h == 'http':
ip = random.choice(PROXY_http)
request.meta['proxy'] = 'http://' + ip
elif h == 'https':
ip = random.choice(PROXY_https)
request.meta['proxy'] = 'https://' + ip

settings.py

DOWNLOADER_MIDDLEWARES = {
'happy2.middlewares.ProxyMiddleware':400,
}

爬虫框架之Scrapy(二)的更多相关文章

  1. scrapy爬虫框架教程(二)-- 爬取豆瓣电影TOP250

    scrapy爬虫框架教程(二)-- 爬取豆瓣电影TOP250 前言 经过上一篇教程我们已经大致了解了Scrapy的基本情况,并写了一个简单的小demo.这次我会以爬取豆瓣电影TOP250为例进一步为大 ...

  2. scrapy爬虫框架教程(二)-- 爬取豆瓣电影

    前言 经过上一篇教程我们已经大致了解了Scrapy的基本情况,并写了一个简单的小demo.这次我会以爬取豆瓣电影TOP250为例进一步为大家讲解一个完整爬虫的流程. 工具和环境 语言:python 2 ...

  3. 06 爬虫框架:scrapy

    爬虫框架:scrapy   一 介绍 Scrapy一个开源和协作的框架,其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的,使用它可以以快速.简单.可扩展的方式从网站中提取所需的数据.但目前S ...

  4. 九、爬虫框架之Scrapy

    爬虫框架之Scrapy 一.介绍 二.安装 三.命令行工具 四.项目结构以及爬虫应用简介 五.Spiders 六.Selectors 七.Items 八.Item Pipelin 九. Dowload ...

  5. Golang 网络爬虫框架gocolly/colly 二 jQuery selector

    Golang 网络爬虫框架gocolly/colly 二 jQuery selector colly框架依赖goquery库,goquery将jQuery的语法和特性引入到了go语言中.如果要灵活自如 ...

  6. Python-S9-Day125-Web微信&爬虫框架之scrapy

    01 今日内容概要 02 内容回顾:爬虫 03 内容回顾:网络和并发编程 04 Web微信之获取联系人列表 05 Web微信之发送消息 06 为什么request.POST拿不到数据 07 到底使用j ...

  7. 爬虫框架之Scrapy

    一.介绍 二.安装 三.命令行工具 四.项目结构以及爬虫应用简介 五.Spiders 六.Selectors 七.Items 八.Item Pipelin 九. Dowloader Middeware ...

  8. 洗礼灵魂,修炼python(72)--爬虫篇—爬虫框架:Scrapy

    题外话: 前面学了那么多,相信你已经对python很了解了,对爬虫也很有见解了,然后本来的计划是这样的:(请忽略编号和日期,这个是不定数,我在更博会随时改的) 上面截图的是我的草稿 然后当我开始写博文 ...

  9. 爬虫框架之Scrapy(一)

    scrapy简介 scrapy是一个用python实现为了爬取网站数据,提取结构性数据而编写的应用框架,功能非常的强大. scrapy常应用在包括数据挖掘,信息处理或者储存历史数据的一系列程序中. s ...

随机推荐

  1. Zepto源码(2016)——Zepto模块(核心模块)

    // Zepto.js // (c) 2010-2016 Thomas Fuchs // Zepto.js may be freely distributed under the MIT licens ...

  2. 更改eclipse的编辑器样式风格

    这里提供两种方法: 1.从网站http://eclipsecolorthemes.org/ 下载,选好自己喜欢的风格后下载epf文件...再使用eclipse的import->preferenc ...

  3. Ubuntu基础教程——安装谷歌Chrome浏览器

    对于刚刚开始使用Ubuntu并想安装谷歌Chrome浏览器的新用户来说,本文所介绍的方法是最快捷的.在Ubuntu上安装谷歌Chrome的方法有很多.一些用户喜欢直接在 谷歌Chrome下载页面 获得 ...

  4. java 中 一个int类型的num,num&1

    n&1 把n与1按位与,因为1除了最低位,其他位都为0,所以按位与结果取决于n最后一位,如果n最后一位是1,则结果为1.反之结果为0.(n&1)==1: 判断n最后一位是不是1(可能用 ...

  5. consoleWriter.go

    package blog4go import ( "fmt" "os" "time" ) // ConsoleWriter is a con ...

  6. BZOJ_1098_[POI2007]办公楼biu_链表优化BFS

    BZOJ_1098_[POI2007]办公楼biu_链表优化BFS Description FGD开办了一家电话公司.他雇用了N个职员,给了每个职员一部手机.每个职员的手机里都存储有一些同事的 电话号 ...

  7. BZOJ_1717_[Usaco2006 Dec]Milk Patterns 产奶的模式_后缀数组

    BZOJ_1717_[Usaco2006 Dec]Milk Patterns 产奶的模式_后缀数组 Description 农夫John发现他的奶牛产奶的质量一直在变动.经过细致的调查,他发现:虽然他 ...

  8. Nginx重新编译添加新模块

    找到nginx的安装包目录,如果没有的话去官网重新下载 查看ngixn版本极其编译参数 /usr/local/nginx/sbin/nginx -V 进入nginx源码目录,重新设置nginx ./c ...

  9. 【转】APP功能测试要领

    也许大家从事APP功能测试已经有一段时间了,心中一定有一个疑问,怎么样才能提高测试的覆盖面呢,我今天把APP功能测试内容分为APP本身的功能,APP关联的事务.APP外部环境.APP其他四大块来给大家 ...

  10. vue.js - 奇怪的 event 对象

    好久都没有写点东西了, 前段时间工作搞得头大,真的就是一起加班到死了.废话不多说,写这篇文章是因为这次因为 event 对象闹了一个乌龙,以此总结一下. 一.event 对象 (一)事件的 event ...