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实现代理服务功能实例
Nov 15 Python
浅析python 内置字符串处理函数的使用方法
Jun 11 Python
pygame实现弹力球及其变速效果
Jul 03 Python
一文总结学习Python的14张思维导图
Oct 17 Python
Python探索之自定义实现线程池
Oct 27 Python
python获取命令行输入参数列表的实例代码
Jun 23 Python
Python中的CSV文件使用&quot;with&quot;语句的方式详解
Oct 16 Python
Python查找最长不包含重复字符的子字符串算法示例
Feb 13 Python
TensorFlow车牌识别完整版代码(含车牌数据集)
Aug 05 Python
keras打印loss对权重的导数方式
Jun 10 Python
python 爬虫基本使用——统计杭电oj题目正确率并排序
Oct 26 Python
Python控制台输出俄罗斯方块的方法实例
Apr 17 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
解决Codeigniter不能上传rar和zip压缩包问题
2014/03/07 PHP
yii2.0实现验证用户名与邮箱功能
2015/12/22 PHP
老生常谈PHP中的数据结构:DS扩展
2017/07/17 PHP
PHP7新增函数
2021/03/09 PHP
XHTML下,JS浮动代码失效的问题
2009/11/12 Javascript
xss文件页面内容读取(解决)
2010/11/28 Javascript
javascript 快速排序函数代码
2012/05/30 Javascript
Jquery实现鼠标移上弹出提示框、移出消失思路及代码
2013/05/19 Javascript
Javascript实现真实字符串剩余字数提示的实例代码
2013/10/22 Javascript
javascript贪吃蛇完整版(源码)
2013/12/09 Javascript
jquery自动将form表单封装成json的具体实现
2014/03/17 Javascript
Javascript核心读书有感之类型、值和变量
2015/02/11 Javascript
codeMirror插件使用讲解
2017/01/16 Javascript
xmlplus组件设计系列之分隔框(DividedBox)(8)
2017/05/02 Javascript
vue-cli构建项目使用 less的方法
2017/10/04 Javascript
使用 vue 实现灭霸打响指英雄消失的效果附demo
2019/05/06 Javascript
如何利用node转发请求详解
2020/09/17 Javascript
JavaScript实现无限轮播效果
2020/11/19 Javascript
[00:49]完美世界DOTA2联赛10月28日开团时刻:随便打
2020/10/29 DOTA
python文件和目录操作函数小结
2014/07/11 Python
零基础写python爬虫之使用Scrapy框架编写爬虫
2014/11/07 Python
Python实现删除当前目录下除当前脚本以外的文件和文件夹实例
2015/07/27 Python
Pandas 合并多个Dataframe(merge,concat)的方法
2018/06/08 Python
Python3实现将本地JSON大数据文件写入MySQL数据库的方法
2018/06/13 Python
Flask Web开发入门之文件上传(八)
2018/08/17 Python
Python pip替换为阿里源的方法步骤
2019/07/02 Python
Python hashlib常见摘要算法详解
2020/01/13 Python
Python接口测试文件上传实例解析
2020/05/22 Python
html5 offlline 缓存使用示例
2013/06/24 HTML / CSS
车辆维修工自我评价怎么写
2013/09/20 职场文书
土建资料员岗位职责
2014/01/04 职场文书
试用期转正鉴定评语
2014/01/27 职场文书
2014年依法行政工作总结
2014/11/19 职场文书
2015年感恩节演讲稿(优选篇)
2015/03/20 职场文书
教师节领导致辞
2015/07/29 职场文书
女人创业励志语录,句句蕴含能量,激发你的潜能
2019/08/20 职场文书