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 相关文章推荐
linux系统使用python监测系统负载脚本分享
Jan 15 Python
Python跳出循环语句continue与break的区别
Aug 25 Python
Python字典操作简明总结
Apr 13 Python
Python快速从注释生成文档的方法
Dec 26 Python
python3.6使用urllib完成下载的实例
Dec 19 Python
python自制包并用pip免提交到pypi仅安装到本机【推荐】
Jun 03 Python
Python object类中的特殊方法代码讲解
Mar 06 Python
python 瀑布线指标编写实例
Jun 03 Python
基于Keras的格式化输出Loss实现方式
Jun 17 Python
python中执行smtplib失败的处理方法
Jul 01 Python
Python3利用openpyxl读写Excel文件的方法实例
Feb 03 Python
Python基础详解之描述符
Apr 28 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
用php获取本周,上周,本月,上月,本季度日期的代码
2009/08/05 PHP
php setcookie(name, value, expires, path, domain, secure) 参数详解
2013/06/28 PHP
php实现水仙花数的4个示例分享
2014/04/08 PHP
PHP实现多文件上传的方法
2015/07/08 PHP
php打包压缩文件之ZipArchive方法用法分析
2016/04/30 PHP
YUI的Tab切换实现代码
2010/04/11 Javascript
ASP.NET jQuery 实例15 通过控件CustomValidator验证CheckBoxList
2012/02/03 Javascript
jquery插件制作 手风琴Panel效果实现
2012/08/17 Javascript
Knockout visible绑定使用方法
2013/11/15 Javascript
node.js中的fs.appendFileSync方法使用说明
2014/12/17 Javascript
JavaScript自定义数组排序方法
2015/02/12 Javascript
JavaScript通过代码调用Flash显示的方法
2016/02/02 Javascript
jQuery实现简单倒计时功能的方法
2016/07/04 Javascript
解决JSON.stringify()自动将中文转译成unicode的问题
2018/01/05 Javascript
微信小程序实现折叠展开效果
2018/07/19 Javascript
jQuery点击页面其他部分隐藏下拉菜单功能
2018/11/27 jQuery
详解简单易懂的 ES6 Iterators 指南和示例
2019/09/24 Javascript
详解为什么Vue中不要用index作为key(diff算法)
2020/04/04 Javascript
JavaScript面试中常考的字符串操作方法大全(包含ES6)
2020/05/10 Javascript
vue实现公告栏文字上下滚动效果的示例代码
2020/06/16 Javascript
[01:19]DOTA2城市挑战赛报名开始 开启你的城市传奇
2018/03/23 DOTA
python中关于时间和日期函数的常用计算总结(time和datatime)
2013/03/08 Python
Python中用Spark模块的使用教程
2015/04/13 Python
详解python解压压缩包的五种方法
2019/07/05 Python
使用python打印十行杨辉三角过程详解
2019/07/10 Python
pytorch之inception_v3的实现案例
2020/01/06 Python
Python+OpenCV实现旋转文本校正方式
2020/01/09 Python
Python turtle画图库&amp;&amp;画姓名实例
2020/01/19 Python
python装饰器实现对异常代码出现进行自动监控的实现方法
2020/09/15 Python
利用Python优雅的登录校园网
2020/10/21 Python
CSS3之边框多颜色Border-color属性使用示例
2013/10/11 HTML / CSS
Julep官网:美容产品和指甲油
2017/02/25 全球购物
类、抽象类、接口的差异
2016/06/13 面试题
幼儿园教师个人反思
2014/01/30 职场文书
2015年全国“爱牙日”宣传活动总结
2015/03/23 职场文书
巴黎圣母院观后感
2015/06/10 职场文书