Python 使用Scrapy刮取使用XMLHttpRequests加载其内容的站点

Python 使用Scrapy刮取使用XMLHttpRequests加载其内容的站点,python,json,ajax,scrapy,Python,Json,Ajax,Scrapy,我试图搜索的网站(在浏览器中)一次返回50个职位。当我尝试使用scrapy返回所有职务头衔时,它只会刮去其中的20个 链接至网页: 当我转到这个页面时,我意识到内容是动态呈现的,所以我右键单击并检查了页面,并在Dev工具中打开XHR>Network选项卡重新加载了它。它显示了两个文件 获取过滤器 装载机会 “LoadOpportunities”似乎很有希望,因此我查看了XHR选项卡下的“Response”,它返回了一个JSON文件,其中包含了我可能需要的所有信息。我使用CTRL-f搜索“标题”

我试图搜索的网站(在浏览器中)一次返回50个职位。当我尝试使用scrapy返回所有职务头衔时,它只会刮去其中的20个

链接至网页:

当我转到这个页面时,我意识到内容是动态呈现的,所以我右键单击并检查了页面,并在Dev工具中打开XHR>Network选项卡重新加载了它。它显示了两个文件

  • 获取过滤器
  • 装载机会
  • “LoadOpportunities”似乎很有希望,因此我查看了XHR选项卡下的“Response”,它返回了一个JSON文件,其中包含了我可能需要的所有信息。我使用CTRL-f搜索“标题”,找到了50个匹配项。太好了

    那就来测试一下。我打开Scrapy Shell并查看了返回JSON的页面:

    在浏览器中打开此页面时,它仅返回(当前)54个职位空缺中的20个。我第一次发现这一点是在我使用json包和ScrapyShell刮取页面时

    当您使用我在“LoadOpportunities”文件下发布的第一个链接查看浏览器中的“Preview”选项卡时,您可以看到它在“opportunities”键下最多有50个值。我正在尝试从每个值中提取“Title”值

    我还创建了一个scraper,它使用HTML响应做同样的事情,但不是特别有用。它没有完成工作,因为它实际上没有与动态网页交互,只是与初始页面连接的部分JSON文件交互

    import scrapy, re, json, requests
    from ..items import MetroSouthItems
    
    class MetroSouth(scrapy.Spider):
        name = "metrosouth"
        start_urls = [
        'https://recruiting.ultipro.com/COM1038/JobBoard/d22da326-8928-4fbc-8b3b-99b6db355d5d/JobBoardView/LoadOpportunities',
        ]
    
        def parse(self, response):
            html_res = response.body
            decoded_res = str(html_res,"utf-8")
            json_file = open("metrosouth.json", "w")
            json_file.write(decoded_res)
            with open("metrosouth.json") as json_data:
                data = json.load(json_data)
                items = MetroSouthItems()
                for i in range(len(data["opportunities"])):
                    items["job_title"] = data["opportunities"][i]["Title"]
                    print(i)
                    yield items
    
    我想把所有可用的作业都刮下来,然后在某个时候把它们铲到数据库中/可能每天早上让爬行器重新运行,这样我就可以跟踪新的列表。现在我让它用新的列表覆盖JSON文件


    如果有人有任何前进的建议或指导,我将不胜感激。我感觉它与Javascript有关,因为它确实说“LoadOpportunities”“是由jslib启动的,但我对javascript没有太多经验,也不知道这意味着什么。

    在页面中,最初他们使用一些额外的负载发出POST请求。我们可以这样复制它:

    import scrapy, json
    
    
    class MetroSouth(scrapy.Spider):
        name = "metrosouth"
        search_url = url = 'https://recruiting.ultipro.com/COM1038/JobBoard/d22da326-8928-4fbc-8b3b-99b6db355d5d/JobBoardView/LoadOpportunities'
    
        def start_requests(self):
            payload = """{"opportunitySearch":{"Top":100,"Skip":0,"QueryString":"","OrderBy":[{"Value":"postedDateDesc","PropertyName":"PostedDate","Ascending":false}],"Filters":[{"t":"TermsSearchFilterDto","fieldName":4,"extra":null,"values":[]},{"t":"TermsSearchFilterDto","fieldName":5,"extra":null,"values":[]},{"t":"TermsSearchFilterDto","fieldName":6,"extra":null,"values":[]}]},"matchCriteria":{"PreferredJobs":[],"Educations":[],"LicenseAndCertifications":[],"Skills":[],"hasNoLicenses":false,"SkippedSkills":[]}}"""
            yield scrapy.Request(self.search_url, method='POST', body=payload)
    
        def parse(self, response):
            j = json.loads(response.text)
            print '======'
            for i, row in enumerate(j.get('opportunities')):
                print i, ' - ', row.get('Title')
            print '======'
    
    检查有效负载中的参数
    Top
    。最初它被设置为50,请求page会给我们20条记录。但我把它增加到了100张,现在我得到了所有54张唱片。
    希望这会有所帮助。

    在页面中,他们最初会使用一些额外的负载发出POST请求。我们可以这样复制它:

    import scrapy, json
    
    
    class MetroSouth(scrapy.Spider):
        name = "metrosouth"
        search_url = url = 'https://recruiting.ultipro.com/COM1038/JobBoard/d22da326-8928-4fbc-8b3b-99b6db355d5d/JobBoardView/LoadOpportunities'
    
        def start_requests(self):
            payload = """{"opportunitySearch":{"Top":100,"Skip":0,"QueryString":"","OrderBy":[{"Value":"postedDateDesc","PropertyName":"PostedDate","Ascending":false}],"Filters":[{"t":"TermsSearchFilterDto","fieldName":4,"extra":null,"values":[]},{"t":"TermsSearchFilterDto","fieldName":5,"extra":null,"values":[]},{"t":"TermsSearchFilterDto","fieldName":6,"extra":null,"values":[]}]},"matchCriteria":{"PreferredJobs":[],"Educations":[],"LicenseAndCertifications":[],"Skills":[],"hasNoLicenses":false,"SkippedSkills":[]}}"""
            yield scrapy.Request(self.search_url, method='POST', body=payload)
    
        def parse(self, response):
            j = json.loads(response.text)
            print '======'
            for i, row in enumerate(j.get('opportunities')):
                print i, ' - ', row.get('Title')
            print '======'
    
    检查有效负载中的参数
    Top
    。最初它被设置为50,请求page会给我们20条记录。但我把它增加到了100张,现在我得到了所有54张唱片。
    希望能有所帮助。

    我自己还没有试过,但我相信你的话。非常感谢你!我确实尝试用一些单独的代码发送有效负载,但无法使其工作。这听起来可能是一个愚蠢的问题,但你如何判断页面何时需要有效负载或其他类型的参数@vezunchik?新代码对我不起作用。我没有复制和粘贴您的代码,但我确实调整了它,使之与您的解决方案相一致。我将在上面添加代码的更新版本以供审阅。如果你发现我做错了什么,请告诉我。我还没有亲自尝试过,但我会相信你的话。非常感谢你!我确实尝试用一些单独的代码发送有效负载,但无法使其工作。这听起来可能是一个愚蠢的问题,但你如何判断页面何时需要有效负载或其他类型的参数@vezunchik?新代码对我不起作用。我没有复制和粘贴您的代码,但我确实调整了它,使之与您的解决方案相一致。我将在上面添加代码的更新版本以供审阅。如果你发现我做错了什么,请告诉我。