根据来自数据的 url 组织抓取的数据

Organizing scraped data based on the url on the data came from

我正在创建一个 Scrapy 程序来抓取个人资料页面以获取数值数据。每个配置文件都有一个部分列出了用户使用的不同标签。这些标签中的每一个 link 到一组分页页面,显示在该标签下制作的所有 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] },
    ...
}