Scrapy:如何将爬取的博客保存在自己的文件中

Scrapy: how to save crawled blogs in their own files

我对 scrapy、python 和一般编码还很陌生。我有一个项目,我想收集博客 posts 以在 Atlas.ti 8 中对它们进行一些内容分析。Atlas 支持 .html、.txt.、docx 和PDF.

我根据scrapy教程搭建了我的爬虫:https://docs.scrapy.org/en/latest/intro/tutorial.html

我的主要问题 是我无法将 post 保存在它们自己的文件中。我可以使用 scrapy crawl <crawler> -o filename.csv 将它们作为一批下载,但是我必须使用 VBA 从 csv 中将 post 逐行放入它们自己的文件中。这是我想避免的步骤。

我当前的代码可以在下面看到。

import scrapy

class BlogCrawler(scrapy.Spider):
name = "crawler"
start_urls = ['url']

def parse(self,response):
    postnro = 0
    for post in response.css('div.post'):
        postnro += 1
        yield {
            'Post nro: ': postnro, 
            'date': post.css('.meta-date::text').get().replace('\r\n\t\ton', '').replace('\t',''),
            'author': post.css('.meta-author i::text').get(),
            'headline': post.css('.post-title ::text').get(),
            'link': post.css('h1.post-title.single a').attrib['href'],
            'text': [item.strip() for item in response.css('div.entry ::text').getall()],
        }

        filename = f'post-{postnro}.html'
        with open(filename, 'wb') as f:
            f.write(???)

    next_page = response.css('div.alignright a').attrib['href']  
    if next_page is not None:
        next_page = response.urljoin(next_page)
        yield scrapy.Request(next_page, callback=self.parse)

我不知道应该如何保存结果。我尝试输入 response.bodyresponse.textTextResponse.textf.write() 无济于事。我还尝试在 for 循环中收集数据并将其保存为:f.write(date + ‘\n’, author + ‘\n'...) 这些方法会生成空的 0 KB 文件。

我将文件类型设置为“html”的原因是因为 Atlas 可以照原样使用,空格不会成为问题。原则上文件类型也可以是.txt。但是,如果我设法将 posts 保存为 html,我就避免了项目中的 次要问题 getall() 创建了一个列表,这就是为什么 strip()、replace() 以及 w3lib 方法难以实现来清理数据的原因。当前代码用逗号替换了空格,这是可读的,但可能会更好。

如果有人对如何将每个博客 post 保存在单独的文件中有想法,每个文件一个 post,我很乐意听取他们的意见。

此致,

背风

经过一夜安眠和几个小时的键盘(和头部)敲击后,设法破解了这个问题。它不漂亮也不优雅,也没有使用 Scrapy 的高级功能,但现在已经足够了。这并没有解决我的次要问题,但我可以接受这是我的第一个爬虫项目。我的代码存在多个问题:

  • "postnro" 没有被更新,所以代码一遍又一遍地写入同一个文件。我无法让它工作,所以我改用“日期”。也可以使用 post 的唯一 ID,但那些太随机了,如果不打开上述文件,我将不知道我正在使用哪个文件。

  • 我不知道如何将 yield 保存到文件中,所以我 for loop 了我想要的内容并一个一个地保存了结果。

  • 我将文件类型从 .html 切换为 .txt,但这花了我一些时间 找出并将 'wb' 切换为普通 'w'.

对于那些感兴趣的工作代码(可以这么说):

def parse(self,response):
    for post in response.css('div.post'):
        date = post.css('.meta-date::text').get().replace('\r\n\t\ton ', '').replace('\t','')
        author = post.css('.meta-author i::text').get()
        headline = post.css('.post-title ::text').get()
        link = post.css('h1.post-title.single a').attrib['href']
        text = [item.strip() for item in post.css('div.entry ::text').getall()]
        filename = f'post-{date}.txt'
        with open(filename, 'w') as f:
            f.write(str(date) + '\n' + str(author) + '\n' + str(headline) + '\n' + str(link) + '\n'+'\n'+ str(text) + '\n')
        
        next_page = response.css('div.alignleft a::attr(href)').get()
        if next_page is not None:
            next_page = response.urljoin(next_page)
            yield scrapy.Request(next_page, callback=self.parse)