摘要:根据Excel文件配置运行多个爬虫
很多时候,我们都需要为每一个单独的网站编写一个爬虫,但有一些情况是你要爬取的几个网站的唯一不同之处在于Xpath表达式不同,此时要分别为每一个网站编写一个爬虫就显得徒劳了,其实可以只使用一个spider就爬取这些相似的网站。
首先创建一个名为generic的工程和一个名为fromcsv的spider:
scrapy startproject generic
cd generic
scrapy genspider fromcsv example.com
然后创建一个csv文件,在文件中填充以下信息:
使用Python的csv库来验证一下
$ python >>> import csv >>> with open("todo.csv", "rU") as f: reader = csv.DictReader(f) for line in reader: print line
输出如下:
注意:todo.csv文件的第一行会自动作为字典的key
现在读取todo.csv文件中的URL和Xpath表达式来运行spider,由于我们并不能提前知道URL,所以要从spider中移除start_urls和allowed_domains部分,使用start_requests()方法,对于csv文件中的每一行都产生一个Request对象,并且将字段名和Xpath表达式放入参数request.mate中,传递到parse函数,然后永Item和ItemLoader来填充item的字段
import csv import scrapy from scrapy.http import Request from scrapy.loader import ItemLoader from scrapy.item import Item, Field class FromcsvSpider(scrapy.Spider): name = "fromcsv" def start_requests(self): with open("todo.csv", "rU") as f: reader = csv.DictReader(f) for line in reader: request = Request(line.pop('url')) #从字典中弹出了key为url的元素 request.meta['fields'] = line yield request def parse(self, response): item = Item() # 在本工程中并没有定义items.py文件 l = ItemLoader(item=item, response=response) for name, xpath in response.meta['fields'].iteritems(): if xpath: item.fields[name] = Field() # 动态创建一个item l.add_xpath(name, xpath) return l.load_item()
fromcsv.py源文件代码地址:
https://github.com/Kylinlin/scrapybook/blob/master/ch05%2Fgeneric%2Fgeneric%2Fspiders%2Ffromcsv.py
运行spider:scrapy crawl fromcsv
由于上面的源码中硬编码了todo.csv文件名,一旦文件名发生了变动就需要修改源代码,这并不是一个好的设计,其实Scrapy使用了一个简便的方式(使用 -a)可以从命令行向spider传送参数,例如:-a variable=value,那么spider就可以在源代码中的self.variable来获取value。为了检查变量名并提供默认值,就使用Python的方法getarrt(self, ‘variable’, ‘default’),所以上面的with语句可以修改为:
with open(getarrt(self, “file”, “todo.csv”), “rU”) as f:
然后在运行spider时通过-a参数来指定csv文件(如果没有使用-a参数,就默认使用todo.csv文件):
scrapy crawl fromcsv –a file=todo.csv