python - Scrapy爬取stackoverflow匹配多个标签的问题

标签 python web-scraping web-crawler scrapy

我现在正在尝试 scrapy。我尝试了 http://doc.scrapy.org/en/1.0/intro/overview.html 中的示例代码页。我尝试使用标签“大数据”提取最近的问题。一切都很好。但是,当我尝试提取带有“bigdata”和“python”标签的问题时,结果不正确,结果中只有“bigdata”标签的问题。但是在浏览器上,我对这两个标签的问题都正确。请在下面找到代码:

import scrapy

class StackOverflowSpider(scrapy.Spider):
    name = 'stackoverflow'
    start_urls = ['https://stackoverflow.com/questions/tagged/bigdata?page=1&sort=newest&pagesize=50']

    def parse(self, response):
        for href in response.css('.question-summary h3 a::attr(href)'):
            full_url = response.urljoin(href.extract())
            yield scrapy.Request(full_url, callback=self.parse_question)

    def parse_question(self, response):
        yield {
            'title': response.css('h1 a::text').extract()[0],
            'votes': response.css('.question .vote-count-post::text').extract()[0],
            'body': response.css('.question .post-text').extract()[0],
            'tags': response.css('.question .post-tag::text').extract(),
            'link': response.url,
        }

当我将 start_urls 更改为

start_urls = ['https://stackoverflow.com/questions/tagged/bigdata+python?page=1&sort=newest&pagesize=50']

结果包含仅带有“大数据”标签的问题。如何仅使用这两个标签获取问题?

编辑:我认为正在发生的事情是 scrapy 从我提供的主页进入带有标签“bigdata”的页面,因为这些标签是指向该标签主页的链接。我如何编辑此代码以使 scrapy 不进入标签页面而只进入该页面中的问题?我尝试使用如下规则,但结果仍然不正确。

rules = (Rule(LinkExtractor(restrict_css='.question-summary h3 a::attr(href)'), callback='parse_question'),)

最佳答案

您拥有的 url(以及初始的 css 规则)是正确的;或者更简单地说:

start_urls = ['https://stackoverflow.com/questions/tagged/python+bigdata']

this 推断,这也将起作用:

start_urls = ['https://stackoverflow.com/questions/tagged/bigdata%20python']

但是,您遇到的问题是,stackoverflow 似乎要求您登录 才能访问多标签搜索功能。要看到这一点,只需退出您的 stackoverflow session 并在您的浏览器中尝试相同的 url。它会将您重定向到仅包含两个标签中第一个标签的结果页面。

TL;DR 获得多标签功能的唯一方法似乎是登录(通过 session cookie 强制执行)

因此,当使用 scrapy 时,修复方法是在执行任何其他操作之前验证 session (登录),然后继续正常解析,一切正常。为此,您可以使用 InitSpider而不是 Spider 并添加适当的登录方法。假设您直接使用 StackOverflow 登录(而不是通过 Google 等),我能够像这样让它按预期工作:

import scrapy
import getpass
from scrapy.spiders.init import InitSpider

class StackOverflowSpider(InitSpider):
    name = 'stackoverflow'
    login_page = 'https://stackoverflow.com/users/login'
    start_urls = ['https://stackoverflow.com/questions/tagged/bigdata+python']

    def parse(self, response):
        ...

    def parse_question(self, response):
        ...

    def init_request(self):
        return scrapy.Request(url=self.login_page, callback=self.login)

    def login(self, response):
        return scrapy.FormRequest.from_response(response,
                    formdata={'email': 'yourEmailHere@foobar.com',
                              'password': getpass.getpass()},
                    callback=self.check_login_response)

    def check_login_response(self, response):
        if "/users/logout" in response.body:
            self.log("Successfully logged in")
            return self.initialized()
        else:
            self.log("Failed login")

关于python - Scrapy爬取stackoverflow匹配多个标签的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32133656/

相关文章:

python - 将命名列表向量从 R 转换为 Python 中的 rpy2?

python - 如何调试它从 Windows 库 ucrtbase 抛出的访问冲突?

python - 在python中使用索引创建一个包含列表子集的新列表

python - 杂乱的扭曲连接在不干净的时尚中消失了。没有代理。已经尝试过标题

python - 临时 Scrapy 中的用户代理轮换

java - 使用 HTMLUNIT 从本地 html 文件读取 html

python - 网页字数统计

.htaccess 和谷歌抓取错误

python - 使用 Python 和 MySQL 进行字符串编码

web-scraping - 用 Cypress 抓取无限滚动 href