- 首页
- 正文
用scrapy爬取古诗词网站
今天我们用另外一种方式来爬取古诗词的网站,目标网站是爬取诗词名句网的所有古诗词,相比于我们之前爬取博客的方法会更简单些,但要对正则表达式有一定的了解
在本文中,可以学到
- CrawlSpider的用法
- settings.py的常用配置
- 如何使用随机浏览器代理
- 如何使用代理ip
- 如何把爬取的数据保存到数据库中
预备工作
- python2.7.10
- scrapy 1.4.0
- virtualenv 15.2.0
- pip install mysql-python
scrapy的架构图
Scrapy中的数据流由执行引擎控制,其过程如下:
1.引擎打开一个网站,找到处理该网站的Spider并向该spider请求第一个要爬取的URL(s)
2.引擎从Spider中获取到第一个要爬取的URL并在调度器(Scheduler)以Request调度
3.引擎向调度器请求下一个要爬取的URL
4.调度器返回下一个要爬取的URL给引擎,引擎将URL通过下载中间件(请求(request)方向)转发给下载器(Downloader)
5.一旦页面下载完毕,下载器生成一个该页面的Response,并将其通过下载中间件(返回(response)方向)发送给引擎。
6.引擎从下载器中接收到Response并通过Spider中间件(输入方向)发送给Spider处理
7.Spider处理Response并返回爬取到的Item及(跟进的)新的Request给引擎
8.引擎将(Spider返回的)爬取到的Item给ItemPipeline,将(Spider返回的)Request给调度器
9.(从第二步)重复直到调度器中没有更多地request,引擎关闭该网站
总结:绿色的箭头是数据流向,有两种情况,这两种情况是可以并行的:
存放url->发送请求->提取url->存放url->发送请示,不停地循环
存放url->发送请求-> 提取数据-> 数据队列处理
创建项目
scrapy startproject gushi
cd gushi
scrapy genspider gushici www.shicimingju.com
项目结构
设置浏览器代理
- 设置固定的浏览器代理
把 settings.py 文件里的 USER_AGENT 选项修改为:
USER_AGENT = '(KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6'
- 设置随机的浏览器代理
在gushi的目录下新建一个useragent.py文件,内容如下:
import random
from scrapy.downloadermiddlewares.useragent import UserAgentMiddleware
class UserAgent(UserAgentMiddleware):
user_agent_list = [
'(KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:70.0) Gecko/20100101 Firefox/70.0'
]
def __init__(self, user_agent=''):
self.user_agent = user_agent
def process_request(self, request, spider):
user_agent = random.choice(self.user_agent_list)
if user_agent:
print '==随机的浏览器=='
print user_agent
print '===='
request.headers.setdefault('User-Agent', user_agent)
修改 settings.py 文件的 DOWNLOADER_MIDDLEWARES 选项
DOWNLOADER_MIDDLEWARES = {
'gushi.useragent.UserAgent': 1
}
设置代理ip
在gushi的目录下新建一个proxymiddle.py文件,内容如下:
-*- coding: utf-8 -*-
import random
class ProxyMiddle(object):
proxy_list = [
'163.125.114.217:8088'
]
def process_request(self, request, spider):
proxy_url = random.choice(self.proxy_list)
if proxy_url:
print '====代理地址====='
print proxy_url
print '================='
request.meta['proxy'] = 'http://' + proxy_url
修改 settings.py 文件的 DOWNLOADER_MIDDLEWARES 选项
DOWNLOADER_MIDDLEWARES = {
'gushi.useragent.UserAgent': 1,
'gushi.proxymiddleware.ProxyMiddle': 10
}
修改创建的爬虫类
- 进入到爬虫类的目录
cd gushi/gushi/spiders/
- 修改 gushici.py 的内容如下
# -*- coding: utf-8 -*-
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
class GushiciSpider(CrawlSpider):
name = 'gushici'
allowed_domains = ['www.shicimingju.com']
start_urls = ['http://www.shicimingju.com/']
rules = (
Rule(LinkExtractor(allow=r'chaxun/list/\d+.html$'),
callback='parse_item', follow=True),
)
def parse_item(self, response):
print '======='
print response.url
print '======='
这里我们只是测试一下能不能爬取类似于chaxun/list/132434.html的所有文章,rules用来定义要爬取页面的规则,follow=True表示用递归来爬取,callback就是用来处理爬取到的页面,后面的逻辑就在这里操作
运行爬虫
scrapy crawl --nolog gushici
保存爬取指定内容到数据库
scrapy把爬取的内容保存到数据库要经过下面三步:
- 先处理要爬取的具体字段
- 在items.py定义要爬取的具体字段
- 在pipelines.py里把爬取的内容插入到数据库
这三个步骤如下:
- 修改 gushici.py 的内容如下:
# -*- coding: utf-8 -*-
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from gushi.items import GushiItem
class GushiciSpider(CrawlSpider):
name = 'gushici'
allowed_domains = ['www.shicimingju.com']
start_urls = ['http://www.shicimingju.com/']
rules = (
Rule(LinkExtractor(allow=r'chaxun/list/\d+.html$'),
callback='parse_item', follow=True),
)
def parse_item(self, response):
gushiItem = GushiItem()
title = response.css('#item_div h1::text').extract_first('')
dynasty = response.css(
'#item_div .niandai_zuozhe::text').extract_first('')
author = response.css(
'#item_div .niandai_zuozhe a::text').extract_first('')
content = response.css(
'#item_div .item_content::text').extract_first('')
tag = response.css('#item_div .shici-mark a::text').extract()
tag = ','.join(tag)
dynasty = ''.join(dynasty)
gushiItem['title'] = title
gushiItem['dynasty'] = dynasty
gushiItem['content'] = content
gushiItem['author'] = author
gushiItem['tag'] = tag
yield gushiItem
- 修改 items.py 的内容如下:
# -*- coding: utf-8 -*-
import scrapy
class GushiItem(scrapy.Item):
# define the fields for your item here like:
title = scrapy.Field() # 标题
dynasty = scrapy.Field() # 朝代
author = scrapy.Field() # 作者
content = scrapy.Field() # 内容
tag = scrapy.Field() # 标签
- 修改 pipelines.py 的内容如下:
# -*- coding: utf-8 -*-
import MySQLdb
import MySQLdb.cursors
from settings import MYSQL_HOST, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DB
class GushiPipeline(object):
def __init__(self):
self.conn = MySQLdb.connect(MYSQL_HOST, MYSQL_USER, MYSQL_PASSWORD,
MYSQL_DB, charset='utf8')
self.cursor = self.conn.cursor()
def process_item(self, item, spider):
title = item['title']
dynasty = item['dynasty']
author = item['author']
content = item['content']
tag = item['tag']
self.cursor.execute(
"SELECT 1 FROM article WHERE title=%s", (title,))
ret = self.cursor.fetchone()
if not ret:
sql = """
INSERT INTO article(title, dynasty, author, content, tag) VALUES(%s, %s, %s, %s, %s)
"""
self.cursor.execute(
sql, (title, dynasty, author, content, tag))
self.conn.commit()
return item
def spider_closed(self, spider):
self.cursor.close()
self.conn.close()
新建一个数据库,同时新建一个article的表和字段
修改 settings.py 文件,修改和添加下面内容:
ITEM_PIPELINES = {
'gushi.pipelines.GushiPipeline': 300,
}
MYSQL_HOST = 'localhost'
MYSQL_USER = 'root'
MYSQL_PASSWORD = 'password'
MYSQL_DB = 'shicimingju'
再次运行爬虫
scrapy crawl --nolog gushici
参考链接
【上一篇】如何使用Python Scrapy开发你的第一个网页爬虫【翻译】
【下一篇】git常用命令