这篇文章主要目的是引入数据库。
任务A:逐页爬取散文网经典散文信息
分析网页特征:翻页是通过对https://www.sanwen.net/sanwen/?p=6最后的数字进行逐加,总共十页考虑使用for循环进行逐页解析。
网页xpath解析发现文章基本信息被放在了一个ul标签下,分装在不同的li标签中,简单提取即可。
新建工程三连:
scrapy startproject sanwen
cd sanwen
scrapy genspider sanwen sanwen.net
然后重点来了,学习python自带数据库模块sqlite3用法,按理来说应该用代码去实现连接数据库,创建数据表和添加表单信息,但是本人还是采用了舒服的可视化软件SQLiteStudio来完成数据库的创建操作。
1. 创建数据库sanwen.sqlite,在sanwen工作目录下
2. 新建表sanwen,添加列“title”,“time”,“author”,“url”,变量类型都设置为VARCHAR,确定生成表格commit structure changes,在数据页就可以看到表格的框架拉
Item编辑:
# -*- coding: utf-8 -*-
import scrapy
class SanwenItem(scrapy.Item):
title=scrapy.Field()
time=scrapy.Field()
author=scrapy.Field()
url=scrapy.Field()
Pipeline编辑:
这部分内容是重点!现学现用。
# -*- coding: utf-8 -*-
import sqlite3
class SanwenPipeline(object):
def open_spider(self,spider): # 打开爬虫时要链接数据库
self.con = sqlite3.connect("sanwen.sqlite") # 链接数据库
self.cu = self.con.cursor() #产生一个新光标
def process_item(self, item, spider): # 处理item
print(spider.name,'pipelines') # 打印传送到管道的信息,看管道是否启用,可免去
insert_sql="insert into sanwen(title,time,author,url) values('{}','{}','{}','{}')".format(item['title'],item['time'],item['author'],item['url']) # item信息引入数据库的插入对象操作
self.cu.execute(insert_sql) # 执行插入操作
self.con.commit() # 提交操作
return item # 函数的返回值是item列表
def spider_close(self,spider): # 关闭爬虫时也关闭数据库链接
self.con.close()
Settings编辑:
# -*- coding: utf-8 -*
BOT_NAME = 'sanwen'
SPIDER_MODULES = ['sanwen.spiders']
NEWSPIDER_MODULE = 'sanwen.spiders'
FEED_EXPORT_ENCODING = 'utf-8' # 中文网页编码要加这句,防止输出乱码
ROBOTSTXT_OBEY = True
LOG_FILE='log.txt' # 将原本终端中显示的日志信息打印到一个log.txt文本文件中,静默爬取
ITEM_PIPELINES = { 'sanwen.pipelines.SanwenPipeline': 300 } # 启用自定义管道,后面的数字只要在1~2000即可,表示一个优先顺序
最后是sanwen_spider的编写:
# -*- coding: utf-8 -*-
import scrapy
from sanwen.items import SanwenItem
class SanwenSpiderSpider(scrapy.Spider):
name = 'sanwen_spider'
allowed_domains = ['sanwen.net']
start_urls = ['https://www.sanwen.net/sanwen/']
def parse(self,response): # 主解析函数,用来产生翻页链接和对应请求响应的
for i in range(1,11): # 注意range(1,11)的取值是从1到10不包括11!
yield scrapy.Request("https://www.sanwen.net/sanwen/?p=%s"%i,callback=self.parse_item)
#上式发送请求,注意%i的变量替代用法,回调的函数是下面的item解析函数
def parse_item(self,response):
print(response)
item=SanwenItem()
lis=response.xpath('//div[@class="categorylist"]/ul/li')
title_list=lis.xpath('h3/a[2]/text()').extract()
time_list=lis.xpath('div/text()').re('\d{4}-\d{2}-\d{2}')
author_list=lis.xpath('div/a/text()').extract()
url_list=lis.xpath('h3/a[2]/@href').extract()
new_url_list=[]
# 爬取的相对链接产生绝对链接
for url_data in url_list:
new_url_list.append("https://www.sanwen.net"+url_data)
for a,b,c,d in zip(title_list,time_list,author_list,new_url_list): # 整合item到一起以便打印出来
print(a,":",":",b,":",c,":",d)
a=a.encode('utf-8') # 没有这四句转码,爬取会出错,应该是中文编码引起的问题
b=b.encode('utf-8')
c=c.encode('utf-8')
d=d.encode('utf-8')
item["title"]=a
item["time"]=b
item["author"]=c
item["url"]=d
yield item
最后运行爬虫scrapy craw lsanwen_spider就可以在SQLiteStudio中刷新看到爬取结果了。
总的来说,编写该爬虫的过程中遇到许多问题,多数跟中文编码导致的错误相关。
对于Pipeline中的内容,打算照搬即可,所有引入数据库的操作基本相似。
像这样不需要cookies访问、也没有js控制的复杂操作的网页爬起来还是相对轻松的,一点体会。