为了磨练我的python和Spark GraphX技能,我一直在尝试构建一个Pinboard用户和书签图。为了做到这一点,我递归刮插件板书签以下列方式:用Scrapy递归地刮擦插接板 - “蜘蛛必须返回请求”错误
- 开始与用户和刮所有书签
- 每个书签,由url_slug鉴定,发现也拯救了所有用户相同的书签。
- 对于从第2步的每个用户,重复上述过程,(去1,...),尽管有来自多个线程在这里(包括使用规则),当我尝试实现这个逻辑试图建议
,我得到以下错误:
ERROR: Spider must return Request, BaseItem, dict or None, got 'generator'
我强烈怀疑有在我的代码这样的搭配yield
/return
做。
这里我的代码的简短描述:
我主要的解析方法找到所有书签项目为一个用户(也是继与同一用户的书签以往任何网页),并产生了parse_bookmark
方法凑这些书签。
class PinSpider(scrapy.Spider):
name = 'pinboard'
# Before = datetime after 1970-01-01 in seconds, used to separate the bookmark pages of a user
def __init__(self, user='notiv', before='3000000000', *args, **kwargs):
super(PinSpider, self).__init__(*args, **kwargs)
self.start_urls = ['https://pinboard.in/u:%s/before:%s' % (user, before)]
self.before = before
def parse(self, response):
# fetches json representation of bookmarks instead of using css or xpath
bookmarks = re.findall('bmarks\[\d+\] = (\{.*?\});', response.body.decode('utf-8'), re.DOTALL | re.MULTILINE)
for b in bookmarks:
bookmark = json.loads(b)
yield self.parse_bookmark(bookmark)
# Get bookmarks in previous pages
previous_page = response.css('a#top_earlier::attr(href)').extract_first()
if previous_page:
previous_page = response.urljoin(previous_page)
yield scrapy.Request(previous_page, callback=self.parse)
此方法刮除信息为书签,包括相应的url_slug,将其存储在PinscrapyItem,然后产生一个scrapy.Request
解析url_slug:
def parse_bookmark(self, bookmark):
pin = PinscrapyItem()
pin['url_slug'] = bookmark['url_slug']
pin['title'] = bookmark['title']
pin['author'] = bookmark['author']
# IF I REMOVE THE FOLLOWING LINE THE PARSING OF ONE USER WORKS (STEP 1) BUT NO STEP 2 IS PERFORMED
yield scrapy.Request('https://pinboard.in/url:' + pin['url_slug'], callback=self.parse_url_slug)
return pin
最后parse_url_slug
方法找到其他用户保存此书签并递归地产生一个scrape.Request
来解析它们中的每一个。
def parse_url_slug(self, response):
url_slug = UrlSlugItem()
if response.body:
soup = BeautifulSoup(response.body, 'html.parser')
users = soup.find_all("div", class_="bookmark")
user_list = [re.findall('/u:(.*)/t:', element.a['href'], re.DOTALL) for element in users]
user_list_flat = sum(user_list, []) # Change from list of lists to list
url_slug['user_list'] = user_list_flat
for user in user_list:
yield scrapy.Request('https://pinboard.in/u:%s/before:%s' % (user, self.before), callback=self.parse)
return url_slug
(为了呈现更简明的方式代码,我去掉其中I存储其它有趣字段或重复检查等份)
任何帮助将不胜感激!
代码运行,谢谢!问题是输出文件是空的。 [这个SO回答](https://stackoverflow.com/questions/17497640/python-scrapy-output-csv-file-empty)和[这一个](https://stackoverflow.com/questions/31890731/scrapy-擦除数据但不输出到文件)表明我应该返回一个项目。我以为我会返回一个,更确切地说,是两个项目(一个PinscrapyItem和一个UrlSlugItem)。我错过了什么吗?我没有使用管道。 – notiv
我忘了提,刮自己的作品('下载/ response_count':41) – notiv
@notiv,看到我编辑 –