1

我是 python 的菜鸟,从今年夏天开始就断断续续地自学。我正在阅读 scrapy 教程,偶尔会阅读有关 html/xml 的更多信息以帮助我理解 scrapy。我对自己的项目是模仿scrapy教程以抓取http://www.gamefaqs.com/boards/916373-pc。我想得到一个线程标题列表以及线程 url,应该很简单!

我的问题在于不理解xpath,我猜也是html。在查看 gamefaqs 网站的源代码时,我不确定要查找什么来获取链接和标题。我想说只看锚标签并抓住文本,但我对如何做感到困惑。

from scrapy.spider import BaseSpider
from scrapy.selector import HtmlXPathSelector
from tutorial.items import DmozItem

class DmozSpider(BaseSpider):
name = "dmoz"
allowed_domains = ["http://www.gamefaqs.com"]
start_urls = ["http://www.gamefaqs.com/boards/916373-pc"]


def parse(self, response):
    hxs = HtmlXPathSelector(response)
    sites = hxs.select('//a')
    items = []
    for site in sites:
        item = DmozItem()
        item['link'] = site.select('a/@href').extract()
        item['desc'] = site.select('text()').extract()
        items.append(item)
    return items

我想改变它以在gamefaqs上工作,那么我会在这条路上放什么?我想象程序返回的结果类似于这个线程名称线程 url 我知道代码并不正确,但有人可以帮我重写它以获得结果,这将帮助我更好地理解抓取过程。

4

1 回答 1

2

网页的布局和组织可能会发生变化,并且基于深度标签的路径可能难以处理。我更喜欢模式匹配链接的文本。即使链接格式发生变化,匹配新模式也很简单。

对于游戏常见问题,文章链接如下所示:

http://www.gamefaqs.com/boards/916373-pc/37644384

那是协议、域名、字面“板”路径。“916373-pc”标识论坛区域,“37644384”是文章 ID。

我们可以使用正则表达式匹配特定论坛区域的链接:

reLink = re.compile(r'.*\/boards\/916373-pc\/\d+$')
if reLink.match(link)

或使用以下任何论坛区域:

reLink = re.compile(r'.*\/boards\/\d+-[^/]+\/\d+$')
if reLink.match(link)

添加与您的代码匹配的链接,我们得到:

import re
reLink = re.compile(r'.*\/boards\/\d+-[^/]+\/\d+$')

def parse(self, response):
    hxs = HtmlXPathSelector(response)
    sites = hxs.select('//a')
    items = []
    for site in sites:
        link = site.select('a/@href').extract()
        if reLink.match(link)
            item = DmozItem()
            item['link'] = link
            item['desc'] = site.select('text()').extract()
            items.append(item)
    return items

许多网站都有单独的摘要和详细信息页面或描述和文件链接,其中路径与带有文章 ID 的模板相匹配。如果需要,您可以像这样解析论坛区域和文章 ID:

reLink = re.compile(r'.*\/boards\/(?P<area>\d+-[^/]+)\/(?P<id>\d+)$')
m = reLink.match(link)
if m:
    areaStr = m.groupdict()['area']
    idStr = m.groupdict()['id']

isStr将是一个字符串,很适合填写 URL 模板,但如果需要计算之前的 ID 等,则将其转换为数字:

idInt = int(idStr)

我希望这有帮助。

于 2012-11-20T01:01:21.857 回答