【问题标题】:Obtaining correct data using Regex/List使用 Regex/List 获取正确的数据
【发布时间】:2014-11-15 06:44:07
【问题描述】:

我正在使用正则表达式解析以下代码(我知道这并不理想,但这是另一天的故事):

data:{
            url: 'stage-team-stat'
        },
        defaultParams: {
            stageId : 9155,
            field: 2,
            teamId: 26
        }
    };

这是使用以下代码解析的(其中 var 是上面的代码):

import re

    stagematch = re.compile("data:\s*{\s*url:\s*'stage-team-stat'\s*},\s*defaultParams:\s*{\s*(.*?),.*},",re.S)

    stagematch2 = re.search(stagematch, var)

        if stagematch2 is not None:
            stagematch3 = stagematch2.group(1)

            stageid = int(stagematch3.split(':', 1)[1])
            stageid = str(stageid)

            teamid = int(stagematch3.split(':', 3)[1])
            teamid = str(teamid)

            print stageid
            print teamid

在本例中,我希望 stageid 为“9155”,teamid 为“32”,但它们都返回为“9155”。

谁能看出我做错了什么?

谢谢

【问题讨论】:

  • 您可以给我们一个MCVE,而不是转储您的所有代码,它只有几行真正重要的行,并包含相关的输入数据,而不是让我们爬取整个网站来获取是吗?
  • @user3045351 我猜@abarnert 的意思是有一个代码 sn-p 可以清楚地说明问题,甚至没有scrapy 参与其中。原因,严格来说,这个问题不是特定于scrapy的,而是更多关于“如何从作为javascript代码sn-p的字符串中提取某些字段”。
  • 现在好多了……但仍然不是很好。该代码无法运行,并且到处都有缩进错误。为什么不直接将变量放入代码中而不是描述如何做呢?
  • 附带说明,如果你使用re.compile,你会得到一个可以直接使用的正则表达式对象:stagematch.match(var),而不是re.match(stagematch, var)
  • 同时,当我针对该数据运行此代码时,re.search 返回None。所以,它实际上根本没有证明你的问题。

标签: javascript python regex web-scraping scrapy


【解决方案1】:

另一种解决方案不是深入研究正则表达式,而是使用 javascript 代码解析器解析 javascript 代码。使用slimit 的示例:

SlimIt 是一个用 Python 编写的 JavaScript 压缩器。它编译 将 JavaScript 转换为更紧凑的代码,以便下载和运行 更快。

SlimIt 还提供了一个包含 JavaScript 解析器的库, 词法分析器、漂亮的打印机和树访问者。

from slimit import ast
from slimit.parser import Parser
from slimit.visitors import nodevisitor

data = """
var defaultTeamStatsConfigParams = {
        data:{
            url: 'stage-team-stat'
        },
        defaultParams: {
            stageId : 9155,
            field: 2,
            teamId: 32
        }
    };

    DataStore.prime('stage-team-stat', defaultTeamStatsConfigParams.defaultParams, [{"RegionId":252,"RegionCode":"gb-eng","TournamentName":"Premier League","TournamentId":2,"StageId":9155,"Field":{"Value":2,"DisplayName":"Overall"},"TeamName":"Manchester United","TeamId":32,"GamesPlayed":4,"Goals":6,"Yellow":7,"Red":0,"TotalPasses":2480,"Possession":247,"AccuratePasses":2167,"AerialWon":61,"AerialLost":49,"Rating":7.01,"DefensiveRating":7.01,"OffensiveRating":6.79,"ShotsConcededIBox":13,"ShotsConcededOBox":21,"TotalTackle":75,"Interceptions":71,"Fouls":54,"WasFouled":46,"TotalShots":49,"ShotsBlocked":9,"ShotsOnTarget":19,"Dribbles":44,"Offsides":3,"Corners":17,"Throws":73,"Dispossesed":36,"TotalClearance":78,"Turnover":0,"Ranking":0}]);

    var stageStatsConfig = {
        id: 'team-stage-stats',
        singular: true,
        filter: {
                instanceType: WS.Filter,
                id: 'team-stage-stats-filter',
                categories: { data: [{ value: 'field' }] },
                singular: true
        },
        params: defaultTeamStatsConfigParams,
        content: {
            instanceType: TeamStageStats,
            view: {
                renderTo: 'team-stage-stats-content'
            }
        }
    };

    var stageStats = new WS.Panel(stageStatsConfig);
    stageStats.load();
"""

parser = Parser()
tree = parser.parse(data)
fields = {getattr(node.left, 'value', ''): getattr(node.right, 'value', '')
          for node in nodevisitor.visit(tree)
          if isinstance(node, ast.Assign)}

print fields['stageId'], fields['field'], fields['teamId']

打印9155 2 32

这里我们遍历语法树节点并根据所有赋值构造一个字典。其中我们有stageIdfieldsteamId


以下是如何将解决方案应用于您的scrapy spider:

from scrapy.contrib.spiders import CrawlSpider, Rule
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
from scrapy.selector import Selector

from slimit import ast
from slimit.parser import Parser
from slimit.visitors import nodevisitor


def get_fields(data):
    parser = Parser()
    tree = parser.parse(data)
    return {getattr(node.left, 'value', ''): getattr(node.right, 'value', '')
            for node in nodevisitor.visit(tree)
            if isinstance(node, ast.Assign)}


class ExampleSpider(CrawlSpider):
    name = "goal2"
    allowed_domains = ["whoscored.com"]
    start_urls = ["http://www.whoscored.com/Teams/32/Statistics/England-Manchester-United"]
    download_delay = 5

    rules = [Rule(SgmlLinkExtractor(allow=('http://www.whoscored.com/Teams/32/Statistics/England-Manchester-United'),deny=('/News', '/Graphics', '/Articles', '/Live', '/Matches', '/Explanations', '/Glossary', 'ContactUs', 'TermsOfUse', 'Jobs', 'AboutUs', 'RSS'),), follow=False, callback='parse_item')]

    def parse_item(self, response):
        sel = Selector(response)
        titles = sel.xpath("normalize-space(//title)")
        myheader = titles.extract()[0]

        script = sel.xpath('//div[@id="team-stage-stats"]/following-sibling::script/text()').extract()[0]
        script_fields = get_fields(script)
        print script_fields['stageId'], script_fields['field'], script_fields['teamId']

【讨论】:

  • 谢谢,这就是我想要的。不过,我不会假装我马上就明白了所有这些,所以我将不得不做一些进一步的阅读。谢谢
猜你喜欢
  • 2020-06-24
  • 1970-01-01
  • 2013-06-19
  • 1970-01-01
  • 1970-01-01
  • 2015-04-15
  • 1970-01-01
  • 2022-11-02
  • 2019-09-12
相关资源
最近更新 更多