对于蜘蛛,抓取周期是这样的:
您首先生成初始请求以抓取第一个 URL,并指定一个回调函数,以使用从这些请求下载的响应调用。
第一个要执行的请求是通过调用 start_requests()(默认情况下)Request为 中指定的 URL 生成start_urls的 parse方法和作为请求的回调函数的方法获得的。
在回调函数中,您解析响应并返回项目对象或这些对象的可迭代对象。这些请求还将包含一个回调,然后将由 Scrapy 下载,然后由指定的回调处理它们的响应。
在回调函数中,您解析页面内容,通常使用选择器(但您也可以使用 BeautifulSoup、lxml 或您喜欢的任何机制)并使用解析的数据生成项目。
最后,从蜘蛛返回的项目通常会保存到数据库或使用Feed 导出写入文件。
即使这个循环适用于任何种类的蜘蛛,也有不同种类的默认蜘蛛捆绑到 Scrapy 中用于不同的目的。我们将在这里讨论这些类型
一、start_requests ()此方法必须返回一个迭代器,其中包含要为该蜘蛛爬行的第一个请求
如果您想更改用于开始抓取域的请求,这是覆盖的方法。例如,如果您需要首先使用 POST 请求登录,您可以执行以下操作:
class MySpider(scrapy.Spider):
name = 'myspider'
def start_requests(self):
return [scrapy.FormRequest("http://www.example.com/login",
formdata={'user': 'john', 'pass': 'secret'},
callback=self.logged_in)]
def logged_in(self, response):
pass
二、allowed_domains
包含允许此蜘蛛抓取的域的可选字符串列表。OffsiteMiddleware如果启用,则不会遵循不属于此列表中指定的域名(或其子域)的 URL 请求 。
假设您的目标网址是https://www.example.com/1.html,然后添加'example.com'到列表中。
三、发送POST请求官方推荐的 Using FormRequest to send data via HTTP POST
return [FormRequest(url="http://www.example.com/post/action",
formdata={'name': 'John Doe', 'age': '27'},
callback=self.after_post)]
这里使用的是FormRequest,并使用formdata传递参数,看到这里也是一个字典。
但是,超级坑的一点来了,使用这种方法发送请求,怎么发都会出问题,返回的数据一直都不是我想要的
payload = {‘password’ : '123123'}
return scrapy.Request(url, body=json.dumps(payload), method='POST', headers={'Content-Type': 'application/json'},)
我们看一下他的源码
class FormRequest(Request):
def __init__(self, *args, **kwargs):
formdata = kwargs.pop('formdata', None)
if formdata and kwargs.get('method') is None:
kwargs['method'] = 'POST'
super(FormRequest, self).__init__(*args, **kwargs)
if formdata:
items = formdata.items() if isinstance(formdata, dict) else formdata
querystr = _urlencode(items, self.encoding)
if self.method == 'POST':
self.headers.setdefault(b'Content-Type', b'application/x-www-form-urlencoded')
self._set_body(querystr)
else:
self._set_url(self.url + ('&' if '?' in self.url else '?') + querystr)
###
def _urlencode(seq, enc):
values = [(to_bytes(k, enc), to_bytes(v, enc))
for k, vs in seq
for v in (vs if is_listlike(vs) else [vs])]
return urlencode(values, doseq=1)
最终我们传递的{‘key’: ‘value’, ‘k’: ‘v’}会被转化为’key=value&k=v’ 并且默认的method是POST,所以直接这样使用会出错



