使用Scrapy使用“加载更多”按钮刮擦无限滚动页面

时间:2017-11-03 20:46:04

标签: python python-3.x web-scraping scrapy

如何使用无限滚动来废弃网页,其中响应是html / text而不是json。

我的第一次尝试是使用Rule和LinkExtractor,这让我获得了大约80%的工作机会

    static $countryList = array(
       ["US" => "USA"],
       ["AL" => "Albania"],
       ["DZ" => "Algeria"],
       //...
       ["UB" => "Uganda"],
       ["US" => "USA"]
      );

我的第二次尝试是使用SCRAPING INFINITE SCROLLING PAGES中的示例,但响应是在text / html而不是json。

点击“加载更多”按钮后,我可以在Chrome开发者工具网络上看到请求网址

class JobsetSpider(CrawlSpider):
    name = 'test'
    allowed_domains = ['jobs.et']
    start_urls = ['https://jobs.et/jobs/']

    rules = (
        Rule(LinkExtractor(allow='https://jobs.et/job/\d+/'), callback='parse_link'),
        Rule(LinkExtractor(), follow=True),
    )

    def parse_link(self, response):
        yield {
            'url': response.url
        }

而“页面”号码增加。

我的问题是

  1. 如何使用scrapy从响应头中提取上面的url 单击“加载更多”按钮
  2. 有没有更好的方法来解决这个问题?

2 个答案:

答案 0 :(得分:3)

忽略“加载更多”按钮。

如您所述,您可以使用网址访问所有作业页面。解析结果的第一页时,查找标题元素

中的作业总数
<h1 class="search-results__title ">
268 jobs found
</h1>

该网站每页显示20个作业,因此您需要刮取268/20 = 13.4(四舍五入)页面。

完成解析第一页后,创建一个生成器以生成后续页面的URL(最多14个循环)并使用另一个函数解析结果。您将需要从网址无法获取的searchId,但它位于页面上的隐藏字段中。

<input type="hidden" name="searchId" value="1509738711.5142">

使用该页码和页码可以构建您的网址

https://jobs.et/jobs/?searchId=<id>&action=search&page=<page>

是的,解析函数将与您的第一页解析器完全相同,但是当您完成所有工作时,最好忍受代码重复,以便将事情直接放在脑海中。

此代码可能类似于

class JobsetSpider(CrawlSpider):
    ...
    start_urls = ['https://jobs.et/jobs/']
    ...

    def parse(self, response):
        # parse the page of jobs
        ...
        job_count = xpath(...)
        search_id = xpath(...)
        pages =  math.ceil(job_count / 20.0)
        for page in range(2, pages):
            url = 'https://jobs.et/jobs/?searchId={}&action=search&page={}'.format(search_id, page)
            yield Request(url, callback = self.parseNextPage)

    def parseNextPage(self, response):
        # parse the next and subsequent pages of jobs
        ...

答案 1 :(得分:1)

您可以添加以下内容:

has_next = response.css('.load-more').extract()
if has_next:
    next_page = response.meta.get('next_page', 1) + 1
    url = response.urljoin(response.css('script').re_first("'(\?searchId.*page=)'") + str(next_page))
    yield Request(url , meta={'next_page': next_page})