我刚刚开始使用scrapy,我想做以下事情
Have a list of n domains
i=0
loop for i to n
Use a (mostly) generic CrawlSpider to get all links (a href) of domain[i]
Save results as json lines
要做到这一点,Spider需要接收它必须抓取的域作为参数。
我已经成功创建了CrawlSpider:
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from scrapy.item import Item, Field
from scrapy.crawler import CrawlerProcess
class MyItem(Item):
#MyItem Fields
class SubsiteSpider(CrawlSpider):
name = "subsites"
start_urls = []
allowed_domains = []
rules = (Rule(LinkExtractor(), callback='parse_obj', follow=True),)
def __init__(self, starturl, allowed, *args, **kwargs):
print(args)
self.start_urls.append(starturl)
self.allowed_domains.append(allowed)
super().__init__(**kwargs)
def parse_obj(self, response):
item = MyItem()
#fill Item Fields
return item
process = CrawlerProcess({'USER_AGENT': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)'})
process.crawl(SubsiteSpider)
process.start()
如果我用scrapy crawl subsites -a starturl=http://example.com -a allowed=example.com -o output.jl
来称呼它
结果就像我想要的那样,所以这部分已经很好了。
我未能做的是创建SubsiteSpider
的多个实例,每个实例都有一个不同的域作为参数。
我尝试过(在SpiderRunner.py中)
from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings
process = CrawlerProcess(get_project_settings())
process.crawl('subsites', ['https://example.com', 'example.com'])
process.start()
变体:
from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings
process = CrawlerProcess(get_project_settings())
allowed = ["example.com"]
start = ["https://example.com"]
process.crawl('subsites', start, allowed)
process.start()
但是我猜错了,因为参数没有正确传递给__init__
,例如TypeError: __init__() missing 1 required positional argument: 'allowed'
或TypeError: __init__() missing 2 required positional arguments: 'starturl' and 'allowed'
(循环尚未实施)
所以,这是我的问题: 1)如果我没有开始通过scrapy shell进行爬网,而是从python代码中进行爬网,那么将参数传递给 init 的正确方法是什么? 2)我怎样才能传递-o output.jl参数? (或者,可以使用allowed参数作为文件名?) 3)我很好地运行每个蜘蛛接一个 - 这样做仍然被认为是最佳/良好的做法吗?您是否可以指向一个更广泛的教程,关于"一次又一次地运行同一个蜘蛛,使用不同的参数(=目标域),可选地并行",如果有的话?
非常感谢大家! 如果有任何拼写错误(不是英语母语者),或者问题/细节不够精确,请告诉我如何纠正错误。
答案 0 :(得分:1)
您的代码存在一些问题:
start_urls
和allowed_domains
是您在__init__()
中修改的类属性,使其在您班级的所有实例中共享。
你应该做的是使它们成为实例属性:
class SubsiteSpider(CrawlSpider):
name = "subsites"
rules = (Rule(LinkExtractor(), callback='parse_obj', follow=True),)
def __init__(self, starturl, allowed, *args, **kwargs):
self.start_urls = [starturl]
self.allowed_domains = [allowed]
super().__init__(*args, **kwargs)
最后3行不应该在你的蜘蛛类文件中,因为你可能不希望每次导入蜘蛛时都运行该代码。
您调用CrawlProcess.crawl()
稍有不妥。您可以像这样使用它,以与您将它们传递给蜘蛛类相同的方式传递参数。 __init__()
。
process = CrawlerProcess(get_project_settings())
process.crawl('subsites', 'https://example.com', 'example.com')
process.start()
我怎样才能传递-o output.jl参数? (或者,可以使用allowed参数作为文件名?
您可以使用custom_settings
获得相同的效果,为每个实例提供不同的FEED_URI
设置。