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.body
、response.text
和 TextResponse.text
到 f.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)
我对 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.body
、response.text
和 TextResponse.text
到 f.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)