python爬蟲庫(kù)scrapy簡(jiǎn)單使用實(shí)例詳解
最近因?yàn)轫?xiàng)目需求,需要寫個(gè)爬蟲爬取一些題庫(kù)。在這之前爬蟲我都是用node或者php寫的。一直聽說python寫爬蟲有一手,便入手了python的爬蟲框架scrapy.
下面簡(jiǎn)單的介紹一下scrapy的目錄結(jié)構(gòu)與使用:
首先我們得安裝scrapy框架
pip install scrapy
接著使用scrapy命令創(chuàng)建一個(gè)爬蟲項(xiàng)目:
scrapy startproject questions
相關(guān)文件簡(jiǎn)介:
scrapy.cfg: 項(xiàng)目的配置文件
questions/: 該項(xiàng)目的python模塊。之后您將在此加入代碼。
questions/items.py: 項(xiàng)目中的item文件.
questions/pipelines.py: 項(xiàng)目中的pipelines文件.
questions/settings.py: 項(xiàng)目的設(shè)置文件.
questions/spiders/: 放置spider代碼的目錄.
questions/spiders/xueersi.py: 實(shí)現(xiàn)爬蟲的主體代碼.
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"] # 目標(biāo)的域名
# 爬取的目標(biāo)地址
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 = ['英語(yǔ)','語(yǔ)文','數(shù)學(xué)']
# 爬蟲開始的時(shí)候,自動(dòng)調(diào)用該方法,如果該方法不存在會(huì)自動(dòng)調(diào)用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方法不存在時(shí),parse方法自動(dòng)被調(diào)用
def parse(self, response):
# xpath的選擇器語(yǔ)法不多介紹,可以直接查看官方文檔
arr = response.xpath("http://ul[@class='pagination']/li/a/text()").extract()
total_page = arr[3]
# 獲取分頁(yè)
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) # 發(fā)出新的請(qǐng)求,獲取每個(gè)分頁(yè)所有題目
# 獲取題目
def getquestion(self,response):
for res in response.xpath('//div[@class="main-wrap"]/ul[@class="items"]/li'):
item = QuestionsItem() # 實(shí)例化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]
# 獲取難度等級(jí)
levels = res.xpath('//div[@class="info"]').re(ur'難度:([\s\S]+?)<')
item['level'] = self.levels.index(levels[0])+1
# 獲取選項(xiàng)
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數(shù)據(jù),傳遞給下一個(gè)請(qǐng)求
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)會(huì)自動(dòng)接收該數(shù)據(jù)
items.py 數(shù)據(jù)結(jié)構(gòu)定義:
# -*- 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 輸出管道(本例子輸出的數(shù)據(jù)寫入本地?cái)?shù)據(jù)庫(kù)):
# -*- 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):
# 建立數(shù)據(jù)庫(kù)連接
self.connect = pymysql.connect('localhost','root','','question',use_unicode=True,charset='utf8')
# 獲取游標(biāo)
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值,使用該字段過濾重復(fù)的題目
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
# 插入選項(xiàng)
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
爬蟲構(gòu)建完畢后,在項(xiàng)目的根目錄下運(yùn)行
scrapy crawl xueersi # scrapy crawl 爬蟲的名稱
更多關(guān)于python爬蟲庫(kù)scrapy使用方法請(qǐng)查看下面的相關(guān)鏈接
- python爬蟲開發(fā)之使用Python爬蟲庫(kù)requests多線程抓取貓眼電影TOP100實(shí)例
- python爬蟲開發(fā)之使用python爬蟲庫(kù)requests,urllib與今日頭條搜索功能爬取搜索內(nèi)容實(shí)例
- 使用Python爬蟲庫(kù)BeautifulSoup遍歷文檔樹并對(duì)標(biāo)簽進(jìn)行操作詳解
- Python爬蟲庫(kù)BeautifulSoup獲取對(duì)象(標(biāo)簽)名,屬性,內(nèi)容,注釋
- Python爬蟲庫(kù)BeautifulSoup的介紹與簡(jiǎn)單使用實(shí)例
- 使用Python爬蟲庫(kù)requests發(fā)送表單數(shù)據(jù)和JSON數(shù)據(jù)
- Python爬蟲庫(kù)requests獲取響應(yīng)內(nèi)容、響應(yīng)狀態(tài)碼、響應(yīng)頭
- 使用Python爬蟲庫(kù)requests發(fā)送請(qǐng)求、傳遞URL參數(shù)、定制headers
- 常用python爬蟲庫(kù)介紹與簡(jiǎn)要說明
- python3第三方爬蟲庫(kù)BeautifulSoup4安裝教程
- 小眾實(shí)用的Python 爬蟲庫(kù)RoboBrowser
相關(guān)文章
Django把SQLite數(shù)據(jù)庫(kù)轉(zhuǎn)換為Mysql數(shù)據(jù)庫(kù)的過程
之前我們默認(rèn)使用的是SQLite數(shù)據(jù)庫(kù),我們開發(fā)完成之后,里面有許多數(shù)據(jù),如果我們想轉(zhuǎn)換成Mysql數(shù)據(jù)庫(kù),那我們先得把舊數(shù)據(jù)從SQLite導(dǎo)出,然后再導(dǎo)入到新的Mysql數(shù)據(jù)庫(kù)里去,這篇文章主要介紹了Django如何把SQLite數(shù)據(jù)庫(kù)轉(zhuǎn)換為Mysql數(shù)據(jù)庫(kù),需要的朋友可以參考下2023-05-05
解決Django no such table: django_session的問題
這篇文章主要介紹了解決Django no such table: django_session的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-04-04
python實(shí)戰(zhàn)游戲之史上最難最虐的掃雷游戲沒有之一
這篇文章主要介紹了使用 python 實(shí)現(xiàn)掃雷游戲,不同于傳統(tǒng)過時(shí)的掃雷,今天我們用 Python 增加了新花樣,文中給大家介紹的非常詳細(xì),需要的朋友可以參考下2021-09-09
keras讀取訓(xùn)練好的模型參數(shù)并把參數(shù)賦值給其它模型詳解
這篇文章主要介紹了keras讀取訓(xùn)練好的模型參數(shù)并把參數(shù)賦值給其它模型詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-06-06
pytorch教程resnet.py的實(shí)現(xiàn)文件源碼分析
torchvision.models這個(gè)包中包含alexnet、densenet、inception、resnet、squeezenet、vgg等常用的網(wǎng)絡(luò)結(jié)構(gòu),并且提供了預(yù)訓(xùn)練模型,可以通過簡(jiǎn)單調(diào)用來讀取網(wǎng)絡(luò)結(jié)構(gòu)和預(yù)訓(xùn)練模型2021-09-09
python爬蟲之urllib,偽裝,超時(shí)設(shè)置,異常處理的方法
今天小編就為大家分享一篇python爬蟲之urllib,偽裝,超時(shí)設(shè)置,異常處理的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-12-12
Python實(shí)現(xiàn)圖片滑動(dòng)式驗(yàn)證識(shí)別方法
驗(yàn)證碼作為一種自然人的機(jī)器人的判別工具,被廣泛的用于各種防止程序做自動(dòng)化的場(chǎng)景中。這篇文章主要介紹了Python實(shí)現(xiàn)圖片滑動(dòng)式驗(yàn)證識(shí)別方法,需要的朋友可以參考下2017-11-11
用Python實(shí)現(xiàn)童年貪吃蛇小游戲功能的實(shí)例代碼
這篇文章主要介紹了用Python實(shí)現(xiàn)童年貪吃蛇小游戲功能的實(shí)例代碼,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12
Python實(shí)現(xiàn)批量文件分類保存的示例代碼
當(dāng)我們電腦里面的文本或者或者文件夾太多了,有時(shí)候想找到自己想要的文件,只能通過去搜索文件名,這樣還是很麻煩的。本文將通過Python語(yǔ)言實(shí)現(xiàn)文件批量分類保存,需要的可以參考一下2022-04-04

