Class scrapy.spiders.CrawlSpider
爬取一般网站常用的 spider。其定义了一些规则(rule)来提供跟进 link 的方便的机制。 也许该 spider 并不是完全适合您的特定网站或项目,但其对很多情况都使用。因此您可以以其为起点,根据需求修改部分方法。当然您也可以实现自己的 spider。
除了从 Spider 继承过来的属性外,其提供了一个新的属性:
rules:
一个包含一个(或多个) Rule 对象的集合(list)。 每个 Rule 对爬取网站的动作定义了特定表现。 Rule 对象在下边会介绍。 如果多个 rule 匹配了相同的链接,则根据他们在本属性中被定义的顺序,第一个会被使用。
爬取规则(Crawling rules)
class scrapy.spiders.Rule(link_extractor, callback=None, cb_kwargs=None, follow=None, process_links=None, process_request=None)
link_extractor 是一个scrapy.linkxtractor.LinkExtractor 对象。其定义了如何从爬取到的页面提取链接。
callback 是一个 callable 或 string(该 spider 中同名的函数将会被调用)。从 link_extractor 中每获取到链接时将会调用该函数。该回调函数接受一个 response 作为其第一个参数,并返回一个包含 Item 以及(或) Request 对象(或者这两者的子类)的列表(list)。(注:编写爬虫规则时,避免把parse当作回调函数)
关于实战中使用CrawlSpider的总结:
1. 对于动态生成的链接,比如抓取网页中“下一页”的链接时,通常链接是动态生成的,此时xpath规则并不能提取到改链接。如下图所示:
图-1 下一页图标
图-2 对应的网页源代码
此时,解决方案是:查看“下一页”链接的规律,一般是"****/index_1.html",
"****/index_2.html"........该类形式。找到规律后手动生成下一页的url,并使用
Class scrapy.spiders.Request对象向生成的url发起请求。
def find_urls(self, response):
if response.body.find(u"下一页") != -1:
url_new = ""
page_num = int(re.search(r'createPageHTML.(\d+), 0, "index", "html".', response.body).group(1))
# 拆分链接,得到自己想要的链接
match = re.search(r'(http://www.nxdjw.gov.cn/[0-9a-zA-Z]{4}/)[a-zA-Z0-9/]*', response.url)
if match:
for i in range(page_num - 1): #生成"index_1.html" -- "index_(page_num-1).html"下一页连接
url_new = match.group(1) + "index_" + str(i + 1) + ".html"
yield Request(url_new)
2. 抓取到的时间格式转换
import time
a = '20160101'
dateArray = time.strptime(a, "%Y%m%d")
otherStyleDate = time.strftime("%Y-%m-%d", dateArray)
3. 正则表达式匹配中文字符(utf-8)
[^\x00-\xff] 匹配一个中文字符
4.
descendant-or-self
descendant-or-self::p 可以匹配某个标签下所有的子标签p
content_list = response.xpath('//div[@class="nr font14_lan"]/descendant-or-self::p/text()').extract()
5. xpath表达式中//text()与/text()区别
//text()表示: 提取当前标签下所有含有文本的子标签的文本信息,而/text()只提取当前标签下的文本信息,若 无文本信息,则返回空(None)
6. 解决scrapy 打印日志信息到控制台中文乱码报错问题
打印到控制台的字符串必须用: str.encode('GB18030')