Scrapy is pretty cool, however I found the documentation to very bare bones, and some simple questions were tough to answer. After putting together various techniques from various stackoverflows I have finally come up with an easy and not overly technical way to run multiple scrapy spiders. I would imagine its less technical than trying to implement scrapyd etc:
So here is one spider that works well at doing it's one job of scraping some data after a formrequest:
from scrapy.spider import BaseSpider
from scrapy.selector import Selector
from scrapy.http import Request
from scrapy.http import FormRequest
from swim.items import SwimItem
class MySpider(BaseSpider):
name = "swimspider"
start_urls = ["swimming website"]
def parse(self, response):
return [FormRequest.from_response(response,formname="AForm",
formdata={"lowage": "20, "highage": "25"}
,callback=self.parse1,dont_click=True)]
def parse1(self, response):
#open_in_browser(response)
hxs = Selector(response)
rows = hxs.xpath(".//tr")
items = []
for rows in rows[4:54]:
item = SwimItem()
item["names"] = rows.xpath(".//td[2]/text()").extract()
item["age"] = rows.xpath(".//td[3]/text()").extract()
item["swimtime"] = rows.xpath(".//td[4]/text()").extract()
item["team"] = rows.xpath(".//td[6]/text()").extract()
items.append(item)
return items
Instead of deliberately writing out the formdata with the form inputs I wanted ie "20" and "25:
formdata={"lowage": "20", "highage": "25}
I used "self." + a variable name:
formdata={"lowage": self.lowage, "highage": self.highage}
This then allows you to call the spider from the command line with the arguments that you want (see below). Use the python subprocess call() function to call those very command lines one after another, easily. It means I can go to my commandline, type "python scrapymanager.py" and have all of my spiders do their thing, each with different arguments passed at their command line, and download their data to the correct place:
#scrapymanager
from random import randint
from time import sleep
from subprocess import call
#free
call(["scrapy crawl swimspider -a lowage='20' -a highage='25' -a sex='W' -a StrkDist='10025' -o free.json -t json"], shell=True)
sleep(randint(15,45))
#breast
call(["scrapy crawl swimspider -a lowage='20' -a highage='25' -a sex='W' -a StrkDist='30025' -o breast.json -t json"], shell=True)
sleep(randint(15,45))
#back
call(["scrapy crawl swimspider -a lowage='20' -a highage='25' -a sex='W' -a StrkDist='20025' -o back.json -t json"], shell=True)
sleep(randint(15,45))
#fly
call(["scrapy crawl swimspider -a lowage='20' -a highage='25' -a sex='W' -a StrkDist='40025' -o fly.json -t json"], shell=True)
sleep(randint(15,45))
So rather than spending hours trying to rig up a complicated single spider that crawls each form in succession (in my case different swim strokes), this is a pretty painless way to run many many spiders "all at once" (I did include a delay between each scrapy call with the sleep() functions).
Hopefully this helps someone.