python爬虫库scrapy简单使用实例详解


Posted in Python onFebruary 10, 2020

最近因为项目需求,需要写个爬虫爬取一些题库。在这之前爬虫我都是用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 爬虫的名称

更多关于python爬虫库scrapy使用方法请查看下面的相关链接

Python 相关文章推荐
利用Python中的输入和输出功能进行读取和写入的教程
Apr 14 Python
Python自动化运维和部署项目工具Fabric使用实例
Sep 18 Python
Python 装饰器使用详解
Jul 29 Python
用tensorflow构建线性回归模型的示例代码
Mar 05 Python
python模块smtplib学习
May 22 Python
Python实现账号密码输错三次即锁定功能简单示例
Mar 29 Python
Python中的几种矩阵乘法(小结)
Jul 10 Python
Pycharm 2020最新永久激活码(附最新激活码和插件)
Sep 17 Python
Python脚本如何在bilibili中查找弹幕发送者
Jun 04 Python
python pymysql库的常用操作
Oct 16 Python
Python中pass的作用与使用教程
Nov 13 Python
Python爬虫之Selenium鼠标事件的实现
Dec 04 Python
tensorflow 实现从checkpoint中获取graph信息
Feb 10 #Python
Python3 集合set入门基础
Feb 10 #Python
Django的CVB实例详解
Feb 10 #Python
TensorFlow实现checkpoint文件转换为pb文件
Feb 10 #Python
Django关于admin的使用技巧和知识点
Feb 10 #Python
Python实现括号匹配方法详解
Feb 10 #Python
Python re正则表达式元字符分组()用法分享
Feb 10 #Python
You might like
磨咖啡豆的密诀
2021/03/03 冲泡冲煮
php foreach 使用&amp;(与运算符)引用赋值要注意的问题
2010/02/16 PHP
PHP的Yii框架中过滤器相关的使用总结
2016/03/29 PHP
Yii使用DbTarget实现日志功能的示例代码
2020/07/21 PHP
ExtJs中简单的登录界面制作方法
2010/08/19 Javascript
js四舍五入数学函数round使用实例
2014/05/09 Javascript
推荐6款基于jQuery实现图片效果插件
2014/12/07 Javascript
jQuery仿gmail实现fixed布局的方法
2015/05/27 Javascript
JQuery给网页更换皮肤的方法
2015/05/30 Javascript
微信小程序 小程序制作及动画(animation样式)详解
2017/01/06 Javascript
CodeMirror js代码加亮使用总结
2017/03/25 Javascript
详解webpack3如何正确引用并使用jQuery库
2017/08/26 jQuery
vue项目中在外部js文件中直接调用vue实例的方法比如说this
2019/04/28 Javascript
vue+django实现一对一聊天功能的实例代码
2019/07/17 Javascript
浅谈Vue 自动化部署打包上线
2020/06/14 Javascript
js里面的变量范围分享
2020/07/18 Javascript
JavaScript中while循环的基础使用教程
2020/08/11 Javascript
[01:32]完美世界DOTA2联赛10月29日精彩集锦
2020/10/30 DOTA
python在linux中输出带颜色的文字的方法
2014/06/19 Python
Python和JavaScript间代码转换的4个工具
2016/02/22 Python
Python基于列表模拟堆栈和队列功能示例
2018/01/05 Python
Tornado高并发处理方法实例代码
2018/01/15 Python
python抓取需要扫微信登陆页面
2019/04/29 Python
Python3实现zip分卷压缩过程解析
2019/10/09 Python
基于Python生成个性二维码过程详解
2020/03/05 Python
keras的ImageDataGenerator和flow()的用法说明
2020/07/03 Python
HTML5页面中尝试调起APP功能
2017/09/12 HTML / CSS
美国高端婴童品牌:Hanna Andersson
2016/10/30 全球购物
畜牧兽医本科生的自我评价
2014/03/03 职场文书
卫生巾广告词
2014/03/18 职场文书
民主生活会对照检查材料范文
2014/10/01 职场文书
数学考试作弊检讨书300字
2015/02/16 职场文书
实习护士自荐信
2015/03/25 职场文书
《有余数的除法》教学反思
2016/02/22 职场文书
Java使用JMeter进行高并发测试
2021/11/23 Java/Android
Python Pandas解析读写 CSV 文件
2022/04/11 Python