python爬虫库scrapy简单使用实例详解
作者:Ricky 发布时间:2022-03-22 23:46:11
标签:python,scrapy
最近因为项目需求,需要写个爬虫爬取一些题库。在这之前爬虫我都是用node或者php写的。一直听说python写爬虫有一手,便入手了python的爬虫框架scrapy.
下面简单的介绍一下scrapy的目录结构与使用:
首先我们得安装scrapy框架
pip install scrapy
接着使用scrapy命令创建一个爬虫项目:
scrapy startproject questions
相关文件简介:
scrapy.cfg: 项目的配置文件
questions/: 该项目的python模块。之后您将在此加入代码。
questions/items.py: 项目中的item文件.
questions/pipelines.py: 项目中的pipelines文件.
questions/settings.py: 项目的设置文件.
questions/spiders/: 放置spider代码的目录.
questions/spiders/xueersi.py: 实现爬虫的主体代码.
xueersi.py 爬虫主体
# -*- coding: utf-8 -*-
import scrapy
import time
import numpy
import re
from questions.items import QuestionsItem
class xueersiSpider(scrapy.Spider):
name = "xueersi" # 爬虫名字
allowed_domains = ["tiku.xueersi.com"] # 目标的域名
# 爬取的目标地址
start_urls = [
"http://tiku.xueersi.com/shiti/list_1_1_0_0_4_0_1",
"http://tiku.xueersi.com/shiti/list_1_2_0_0_4_0_1",
"http://tiku.xueersi.com/shiti/list_1_3_0_0_4_0_1",
]
levels = ['偏易','中档','偏难']
subjects = ['英语','语文','数学']
# 爬虫开始的时候,自动调用该方法,如果该方法不存在会自动调用parse方法
# def start_requests(self):
# yield scrapy.Request('http://tiku.xueersi.com/shiti/list_1_2_0_0_4_0_39',callback=self.getquestion)
# start_requests方法不存在时,parse方法自动被调用
def parse(self, response):
# xpath的选择器语法不多介绍,可以直接查看官方文档
arr = response.xpath("//ul[@class='pagination']/li/a/text()").extract()
total_page = arr[3]
# 获取分页
for index in range(int(total_page)):
yield scrapy.Request(response.url.replace('_0_0_4_0_1',"_0_0_4_0_"+str(index)),callback=self.getquestion) # 发出新的请求,获取每个分页所有题目
# 获取题目
def getquestion(self,response):
for res in response.xpath('//div[@class="main-wrap"]/ul[@class="items"]/li'):
item = QuestionsItem() # 实例化Item类
# 获取问题
questions = res.xpath('./div[@class="content-area"]').re(r'<div class="content-area">?([\s\S]+?)<(table|\/td|div|br)')
if len(questions):
# 获取题目
question = questions[0].strip()
item['source'] = question
dr = re.compile(r'<[^>]+>',re.S)
question = dr.sub('',question)
content = res.extract()
item['content'] = question
# 获取课目
subject = re.findall(ur'http:\/\/tiku\.xueersi\.com\/shiti\/list_1_(\d+)',response.url)
item['subject'] = self.subjects[int(subject[0])-1]
# 获取难度等级
levels = res.xpath('//div[@class="info"]').re(ur'难度:([\s\S]+?)<')
item['level'] = self.levels.index(levels[0])+1
# 获取选项
options = re.findall(ur'[A-D][\..]([\s\S]+?)<(\/td|\/p|br)',content)
item['options'] = options
if len(options):
url = res.xpath('./div[@class="info"]/a/@href').extract()[0]
request = scrapy.Request(url,callback=self.getanswer)
request.meta['item'] = item # 缓存item数据,传递给下一个请求
yield request
#for option in options:
# 获取答案
def getanswer(self,response):
res = response.xpath('//div[@class="part"]').re(ur'<td>([\s\S]+?)<\/td>')
con = re.findall(ur'([\s\S]+?)<br>[\s\S]+?([A-D])',res[0]) # 获取含有解析的答案
if con:
answer = con[0][1]
analysis = con[0][0] # 获取解析
else:
answer = res[0]
analysis = ''
if answer:
item = response.meta['item'] # 获取item
item['answer'] = answer.strip()
item['analysis'] = analysis.strip()
item['answer_url'] = response.url
yield item # 返回item,输出管道(pipelines.py)会自动接收该数据
items.py 数据结构定义:
# -*- coding: utf-8 -*-
# Define here the models for your scraped items
#
# See documentation in:
# https://doc.scrapy.org/en/latest/topics/items.html
import scrapy
class QuestionsItem(scrapy.Item):
content = scrapy.Field()
subject = scrapy.Field()
level = scrapy.Field()
answer = scrapy.Field()
options = scrapy.Field()
analysis = scrapy.Field()
source = scrapy.Field()
answer_url = scrapy.Field()
pass
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
import pymysql
import md5
class QuestionsPipeline(object):
def __init__(self):
# 建立数据库连接
self.connect = pymysql.connect('localhost','root','','question',use_unicode=True,charset='utf8')
# 获取游标
self.cursor = self.connect.cursor()
print("connecting mysql success!")
self.answer = ['A','B','C','D']
def process_item(self, item, spider):
content = pymysql.escape_string(item['content'])
# 获取题目hash值,使用该字段过滤重复的题目
m1 = md5.new()
m1.update(content)
hash = m1.hexdigest()
selectstr = "select id from question where hash='%s'"%(hash)
self.cursor.execute(selectstr)
res = self.cursor.fetchone()
# 过滤相同的题目
if not res:
# 插入题目
sqlstr = "insert into question(content,source,subject,level,answer,analysis,hash,answer_url) VALUES('%s','%s','%s','%s','%s','%s','%s','%s')"%(content,pymysql.escape_string(item['source']),item['subject'],item['level'],item['answer'],pymysql.escape_string(item['analysis']),hash,item['answer_url'])
self.cursor.execute(sqlstr)
qid = self.cursor.lastrowid
# 插入选项
for index in range(len(item['options'])):
option = item['options'][index]
answer = self.answer.index(item['answer'])
if answer==index:
ans = '2'
else:
ans = '1'
sqlstr = "insert into options(content,qid,answer) VALUES('%s','%s','%s')"%(pymysql.escape_string(option[0]),qid,ans)
self.cursor.execute(sqlstr)
self.connect.commit()
#self.connect.close()
return item
爬虫构建完毕后,在项目的根目录下运行
scrapy crawl xueersi # scrapy crawl 爬虫的名称
来源:https://www.cnblogs.com/dudeyouth/p/8795409.html
0
投稿
猜你喜欢
- location是javascript里边管理地址栏的内置对象,比如location.href就管理页面的url,用location.hre
- 1.open使用open打开文件后一定要记得调用文件对象的close()方法。比如可以用try/finally语句来确保最后能关闭文件。fi
- 说到排序,很多人可能第一想到的就是sorted,但是你可能不知道python中其实还有还就中方法哟,并且好多种场景下效率都会比sorted高
- 定义行为要定义行为,通过继承 yii\base\Behavior 或其子类来建立一个类。如:namespace app\components
- 编写 models.py 文件from django.db import models# Create your models here.c
- 简介今天试着用ptyhon做了一个抓取网页内容,并生成word文档的功能,功能很简单,做一下记录以备以后用到。生成word用到了第三方组件p
- 简单低级的爬虫速度快,伪装度低,如果没有反爬机制,它们可以很快的抓取大量数据,甚至因为请求过多,造成服务器不能正常工作。而伪装度高的爬虫爬取
- 今天想直观的展示一下数据就用到了matplotlib模块,之前都是一张图只有一条曲线,现在想同一个图片上绘制多条曲线来对比,实现很简单,具体
- 先上图片词云图需要模板pip install jiebapip install wordcloud还需要安装另外两个东西这两个我也不太懂借鉴
- object.OpenTextFile(filename[, iomode[, create[, format]]]) 参数 object
- 前言:近我使用 Go 语言完成了一个正式的 Web 应用,有一些方面的问题在使用 Go 开发 Web 应用过程中比较重要。过去,我将 Web
- 概述os.access() 方法使用当前的uid/gid尝试访问路径。大部分操作使用有效的 uid/gid, 因此运行环境可以在 suid/
- 其实 selenium启动窗口的时候就是 使用了subprocess.Popen 启动的驱动程序的,只要在启动的时候加上启动不显示窗口的参数
- 1、 利用操作符+比如:a = [1,2,3]b = [4,5,6]c = a+bc的结果:[1,2,3,4,5,6] 2 利用e
- 软删除简单的说,就是当执行删除操作的时候,不正真执行删除操作,而是在逻辑上删除一条记录。这样做的好处是可以统计数据,可以进行恢复操作等等。预
- 今天看YUI的视频教程,YUI的工程师介绍的一款在线的图片压缩工具,也许你用过,也许没有,不过我这里强烈推荐大家用一下,我用smush.it
- 大家好,我们的git专题已经更新结束了,所以开始继续给大家写一点设计模式的内容。今天给大家介绍的设计模式非常简单,叫做iterator,也就
- OpenCVOpenCV 是计算机视觉领域最受欢迎的开源库,起初它由 C/C ++ 编写,现在用 Python 也能使用。OpenCV 可以
- 新标准的熟悉和入门内容: 还在用 HTML 编写文档?如果是的话,就不符合当前标准了。2000 年&
- 本文实例讲述了PHP函数shuffle()取数组若干个随机元素的方法。分享给大家供大家参考,具体如下:有时候我们需要取数组中若干个随机元素(