根据来自数据的 url 组织抓取的数据
Organizing scraped data based on the url on the data came from
我正在创建一个 Scrapy 程序来抓取个人资料页面以获取数值数据。每个配置文件都有一个部分列出了用户使用的不同标签。这些标签中的每一个 link 到一组分页页面,显示在该标签下制作的所有 post,每个 post 的字数。每个配置文件都具有相同的布局和相同的选择器,所以不用担心。
我想要从每个配置文件中获得的数据:
- 每个标签中 post 的数量
- 每个标签的总字数
我在 start_urls
中列出了我想要抓取的所有配置文件,因此无需爬网即可查找配置文件。我只想知道使用 Item Loaders and/or 管道确保数据按配置文件和标签组织的逻辑。这是我的蜘蛛的一些伪代码,可以让事情更清楚
class ProfileScraper(scrapy.Spider):
name = 'scraper'
start_urls = ['https://example.com/fancyuser1', 'https://example.com/coooluser2', 'https://example.com/superuser3', ... ]
def parse(self, response):
tags_pages = response.css('.tags + a').getall()
yield from response.followall(tags_pages, callback=self.parse_tagspage)
def parse_tagspage(self, response):
number_of_posts = response.css('div.postcount span::text')
number_of_words = response.css('div.wordcount span::text').getall()
page_sum_words = sum(int(number) for number in number_of_words if number.strip())
# pseudo-code is here
all_that_data[username].apphend([number_of_posts, page_sum_words])
# let's pretend there is only one page for this tag
我理想中的 dict
如下所示。二维数组表示不同的标签和每个标签的 post 和单词数。
all_that_data = {
'fancyuser1': [[3, 200], [10, 500], [6, 450]],
'coooluser2': [[1, 150], [6, 800], [2, 100], [4, 400]],
'superuser3': [[3, 350], [5, 400]],
...
}
每个配置文件可以有任意多个标签,所以当我遵循这些 links 时,我如何确保每个标签的数据彼此分开,但都嵌套在正确的配置文件下?
在您的 parse_tagspage
中,您需要:
yield { 'username': username, 'number_of_posts': number_of_posts, 'page_sum_words': page_sum_words}
并且在您的 pipelines.py
中,您可以使用 all_that_data
class 变量来填充 process_item
这是对我有用的完整解决方案。这里的另一个答案确实帮助我思考了使用管道时数据经过的过程。
parse_tagspage
应该有这个,这将产生要由管道处理的数据
url_info = response.url.replace('https://example.com/','').split('/') ## get important parts of the url
userkey = url_info[0] ## just get profile name part
tag = url_info[1].replace('posts?tag=','') ## just get tag part of link
yield { 'username': userkey, 'tag': tag, 'number_of_posts': number_of_posts, 'page_sum_words': page_sum_words }
我的管道获取该信息并将其转换为字典。这不是我最初想要的确切组织,但很容易创建一个新的 dict 并使用通过现有 dict 的循环使用相同的数据填充它。长话短说,我得到了我想要的二维数组。
## self.all_that_data is a dict defined in the pipeline's __init__
def process_item(self, item, spider):
## initiate local variables
username = item['username']
tag = item['tag']
number_of_posts = item['number_of_posts']
page_sum_words = item['page_sum_words']
if not username in self.all_that_data:
self.all_that_data[username] = {}
self.all_that_data[username][tag] = [number_of_posts, page_sum_words]
else:
if not tag in self.full_data[username]:
self.all_that_data[username][tag] = [number_of_posts, page_sum_words]
else:
## this is used if one tag has multiple pages, each page sum is added
self.all_that_data[username][tag][1] += word_count
return item ## process_item function has to have this, even if item isn't changed
all_that_data
最终看起来像这样:
all_that_data = {
'fancyuser1': { 'fun_tag':[3, 200], 'happy_tag':[10, 500], 'meme_tag':[6, 450] },
'coooluser2': { 'happy_tag':[1, 150], 'fun_tag':[6, 800], 'super_tag':[4, 400] },
'superuser3': { 'happy_tag':[3, 350], 'super_tag':[4, 400] },
...
}
我正在创建一个 Scrapy 程序来抓取个人资料页面以获取数值数据。每个配置文件都有一个部分列出了用户使用的不同标签。这些标签中的每一个 link 到一组分页页面,显示在该标签下制作的所有 post,每个 post 的字数。每个配置文件都具有相同的布局和相同的选择器,所以不用担心。
我想要从每个配置文件中获得的数据:
- 每个标签中 post 的数量
- 每个标签的总字数
我在 start_urls
中列出了我想要抓取的所有配置文件,因此无需爬网即可查找配置文件。我只想知道使用 Item Loaders and/or 管道确保数据按配置文件和标签组织的逻辑。这是我的蜘蛛的一些伪代码,可以让事情更清楚
class ProfileScraper(scrapy.Spider):
name = 'scraper'
start_urls = ['https://example.com/fancyuser1', 'https://example.com/coooluser2', 'https://example.com/superuser3', ... ]
def parse(self, response):
tags_pages = response.css('.tags + a').getall()
yield from response.followall(tags_pages, callback=self.parse_tagspage)
def parse_tagspage(self, response):
number_of_posts = response.css('div.postcount span::text')
number_of_words = response.css('div.wordcount span::text').getall()
page_sum_words = sum(int(number) for number in number_of_words if number.strip())
# pseudo-code is here
all_that_data[username].apphend([number_of_posts, page_sum_words])
# let's pretend there is only one page for this tag
我理想中的 dict
如下所示。二维数组表示不同的标签和每个标签的 post 和单词数。
all_that_data = {
'fancyuser1': [[3, 200], [10, 500], [6, 450]],
'coooluser2': [[1, 150], [6, 800], [2, 100], [4, 400]],
'superuser3': [[3, 350], [5, 400]],
...
}
每个配置文件可以有任意多个标签,所以当我遵循这些 links 时,我如何确保每个标签的数据彼此分开,但都嵌套在正确的配置文件下?
在您的 parse_tagspage
中,您需要:
yield { 'username': username, 'number_of_posts': number_of_posts, 'page_sum_words': page_sum_words}
并且在您的 pipelines.py
中,您可以使用 all_that_data
class 变量来填充 process_item
这是对我有用的完整解决方案。这里的另一个答案确实帮助我思考了使用管道时数据经过的过程。
parse_tagspage
应该有这个,这将产生要由管道处理的数据
url_info = response.url.replace('https://example.com/','').split('/') ## get important parts of the url
userkey = url_info[0] ## just get profile name part
tag = url_info[1].replace('posts?tag=','') ## just get tag part of link
yield { 'username': userkey, 'tag': tag, 'number_of_posts': number_of_posts, 'page_sum_words': page_sum_words }
我的管道获取该信息并将其转换为字典。这不是我最初想要的确切组织,但很容易创建一个新的 dict 并使用通过现有 dict 的循环使用相同的数据填充它。长话短说,我得到了我想要的二维数组。
## self.all_that_data is a dict defined in the pipeline's __init__
def process_item(self, item, spider):
## initiate local variables
username = item['username']
tag = item['tag']
number_of_posts = item['number_of_posts']
page_sum_words = item['page_sum_words']
if not username in self.all_that_data:
self.all_that_data[username] = {}
self.all_that_data[username][tag] = [number_of_posts, page_sum_words]
else:
if not tag in self.full_data[username]:
self.all_that_data[username][tag] = [number_of_posts, page_sum_words]
else:
## this is used if one tag has multiple pages, each page sum is added
self.all_that_data[username][tag][1] += word_count
return item ## process_item function has to have this, even if item isn't changed
all_that_data
最终看起来像这样:
all_that_data = {
'fancyuser1': { 'fun_tag':[3, 200], 'happy_tag':[10, 500], 'meme_tag':[6, 450] },
'coooluser2': { 'happy_tag':[1, 150], 'fun_tag':[6, 800], 'super_tag':[4, 400] },
'superuser3': { 'happy_tag':[3, 350], 'super_tag':[4, 400] },
...
}