scrapy爬取csdn博客文章

本文为爬取某人csdn博客中文章题目和url,因为作者本人爬取的就是他自己的博客,所以我这里不做更改,只是为学习和记录一种scrapy的方法。   

1.创建project

1
2
3
4
5
6
7
8
9
10
nick@ubuntu:~$ scrapy startproject csndblog
2015-09-07 22:24:29 [scrapy] INFO: Scrapy 1.0.2 started (bot: scrapybot)
2015-09-07 22:24:29 [scrapy] INFO: Optional features available: ssl, http11, boto
2015-09-07 22:24:29 [scrapy] INFO: Overridden settings: {}
New Scrapy project 'csndblog' created in:
/home/nick/csndblog
You can start your first spider with:
cd csndblog
scrapy genspider example example.com
  • items.py编写

在这里为清晰说明,只提取文章名称和文章网址。

1
2
3
4
5
import scrapy
class CsndblogItem(scrapy.Item):
article_name = scrapy.Field()
article_url = scrapy.Field()
pass
  • pipelines.py编写
1
2
3
4
5
6
7
8
9
10
11
import codecs
import json
class CsdnblogPipeline(object):
def __init__(self):
self.file = codecs.open('csdnblog_data.json', mode='wb', encoding='utf-8')
def process_item(self, item, spider):
line = json.dumps(dict(item)) + '\n'
self.file.write(line.decode("unicode_escape"))
return item
  • settings.py编写

对于setting文件,他作为配置文件,主要是至执行对spider的配置。一些容易被改变的配置参数可以放在spider类的编写中,而几乎在爬虫运行过程中不改变的参数在settings.py中进行配置。
将ITEM_PIPELINES的注释去掉,并将其中内容改为:
'csdnblog.pipelines.CsdnblogPipeline': 300,这个CSdnblogPipeline就是在pipelines中定义的。

再加上一句COOKIES_ENABLED = False
这里将COOKIES_ENABLED参数置为True,使根据cookies判断访问的站点不能发现爬虫轨迹,防止被ban。

2.编写爬虫

爬虫编写始终是重头戏。原理是分析网页得到“下一篇”的链接,并返回Request对象。进而继续爬取下一篇文章,直到最后一篇文章。
在spider文件夹下创建文件csdnblog_spider.py,文件代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#coding:utf-8
from scrapy.spiders import Spider
from scrapy.http import Request
from scrapy.selector import Selector
from csdnblog.items import CsdnblogItem
class CSDNBlogSpider(Spider):
name = "csdnblog"
download_delay = 1#减慢爬取速度 为1s
allowed_domains = ["blog.csdn.net"]
#第一篇文章地址
start_urls = ["http://blog.csdn.net/u012150179/article/details/11749017"]
def parse(self, response):
sel = Selector(response)
item = CsdnblogItem()
article_url = str(response.url)#本篇文章的url
article_name = sel.xpath('//div[@id="article_details"]/div/h1/span/a/text()').extract()[0]
item['article_name'] = article_name
item['article_url'] = article_url.encode('utf-8')
yield item
#获得下一篇文章的url
url = sel.xpath('//li[@class="next_article"]/a/@href').extract()[0]
urls = "http://blog.csdn.net" + url
yield Request(urls, callback=self.parse)

  先说下爬虫的整个运行过程,我们将这个博客的第一篇文章的url个爬虫程序作为start_urls,因为在阅读文章的最下面都有一个上一篇和下一篇的链接,这个链接的a标签的class属性值为”next_article”是唯一的:所以在获取到一篇文章后只需得到这个便签中的url即可,它与csdn的blog域名连接起来就是下一篇文章的url,只要持续这个过程直到最后一篇文章没有这个便签了就相当于结束了。下面来分析上面的代码:  

  • download_delay参数设置为1,将下载器下载下一个页面前的等待时间设置为1s,也是防止被ban的策略之一。主要是减轻服务器端负载。

  • 因为我们的基类是from scrapy.spiders import Spider,parse函数为爬虫默认的回调函数,所有对信息的处理都在它其中进行。

  • 文章的题目是利用xpath去匹配的,XPath 是一门在 XML 文档中查找信息的语言,css选择器和XPath是许多爬虫中匹配信息的两种方式,不了解的推荐去w3school学习一下,css选择器XPath

  • response.url是此次response的地址,也就是我们这次访问的地址。

  • 用我理解解释下yield,我也是刚接触这个函数,网上给的太晦涩了,我就说下在这的含义:正常一个函数返回是用return,然后就回到调用此函数的地方去了,return下面的语句就都不执行了,而yield的作用和return在某种程度上是类似的,它也起到返回的作用,但是我们可以看到它的下面还有语句,这就是yield和return的不同之处,如果yield执行完继续去下面的语句寻找是否还有另一个yield,如果找到了,那么这其中的所有代码都会执行,直到某一个yield发现他的下面没有其他yield了那么这个函数才算正式退出了。

  • yield Request(url, callback=self.parse) 这句话的意思是将从页面中提取出的下一篇文章的地址返回给引擎,样子好像似递归一样,这样就实现了继续循环,也就是“自动下一页的爬取”。

3.运行

进入csdnblog工程目录,运行

1
nick@ubuntu:~/csdnblog$ scrapy crawl csdnblog

最终保存到csdnblog_data.json文件中,下面是截取的一部分

1
2
3
4
5
6
7
8
9
10
11
12
{"article_name": "
写在开始
", "article_url": "http://blog.csdn.net/u012150179/article/details/11749017"}
{"article_name": "
Python相关介绍(很好)
", "article_url": "http://blog.csdn.net/u012150179/article/details/11836503"}
{"article_name": "
脚本语言为何难堪重任?
", "article_url": "http://blog.csdn.net/u012150179/article/details/11837005"}
{"article_name": "
ubuntu study
", "article_url": "http://blog.csdn.net/u012150179/article/details/12073527"}

此工程github地址:https://github.com/lowkeynic4/crawl/tree/master/csdnblog

本文转自:http://blog.csdn.net/u012150179/article/details/34486677