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中ConfigParse模块的用法
Sep 29 Python
python实现从一组颜色中找出与给定颜色最接近颜色的方法
Mar 19 Python
python去除文件中空格、Tab及回车的方法
Apr 12 Python
Python闭包之返回函数的函数用法示例
Jan 27 Python
python实现求解列表中元素的排列和组合问题
Mar 15 Python
Python3对称加密算法AES、DES3实例详解
Dec 06 Python
对Python 简单串口收发GUI界面的实例详解
Jun 12 Python
python修改字典键(key)的方法
Aug 05 Python
python并发编程多进程 互斥锁原理解析
Aug 20 Python
如何基于python操作json文件获取内容
Dec 24 Python
Python 3.8 新功能大揭秘【新手必学】
Feb 05 Python
浅谈python中频繁的print到底能浪费多长时间
Feb 21 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 配置文件中open_basedir选项作用
2009/07/19 PHP
PHP 查找字符串常用函数介绍
2012/06/07 PHP
php gzip压缩输出的实现方法
2013/04/27 PHP
Win7下手动安装apache2.2、php5.4笔记
2015/04/03 PHP
CentOS系统中PHP安装扩展的方式汇总
2017/04/09 PHP
php中的异常和错误浅析
2017/05/03 PHP
php使用curl伪造浏览器访问操作示例
2019/09/30 PHP
javascript事件函数中获得事件源的两种不错方法
2014/03/17 Javascript
javascript上下方向键控制表格行选中并高亮显示的方法
2015/02/13 Javascript
JavaScript获取IP获取的是IPV6 如何校验
2016/06/12 Javascript
indexedDB bootstrap angularjs之 MVC DOMO (应用示例)
2016/06/20 Javascript
深入理解js generator数据类型
2016/08/16 Javascript
jQuery选择器实例应用
2017/01/05 Javascript
详解vue2路由vue-router配置(懒加载)
2017/04/08 Javascript
vue-cli构建项目使用 less的方法
2017/10/04 Javascript
vue中动态绑定表单元素的属性方法
2018/02/23 Javascript
微信小程序实现天气预报功能
2018/07/18 Javascript
Angularjs实现数组随机排序的方法
2018/10/02 Javascript
Vue.js中Line第三方登录api的实现代码
2020/06/29 Javascript
解决vue一个页面中复用同一个echarts组件的问题
2020/07/19 Javascript
Python实现文件信息进行合并实例代码
2018/01/17 Python
django如何连接已存在数据的数据库
2018/08/14 Python
解决PyCharm的Python.exe已经停止工作的问题
2018/11/29 Python
Django实现微信小程序的登录验证功能并维护登录态
2019/07/04 Python
Python+OpenCV实现图像的全景拼接
2020/03/05 Python
中国宠物用品商城:E宠商城
2016/08/27 全球购物
德国运动营养和健身网上商店:Myprotein.de
2018/07/18 全球购物
美国唇部护理专家:Sara Happ
2019/06/19 全球购物
英国著名的美容护肤和护发产品购物网站:Lookfantastic
2020/11/23 全球购物
气象学专业个人求职信
2014/04/22 职场文书
舞蹈教育学专业求职信
2014/06/29 职场文书
导游词之杭州西湖
2019/09/19 职场文书
2021-4-5课程——SQL Server查询【3】
2021/04/05 SQL Server
为Java项目添加Redis缓存的方法
2021/05/18 Redis
对PyTorch中inplace字段的全面理解
2021/05/22 Python
使用 Koa + TS + ESLlint 搭建node服务器的过程详解
2022/05/30 NodeJs