无法理解在源代码中查找的位置,以便创建Web scraper

时间:2012-11-20 00:49:59

标签: python web-scraping web-crawler

我是蟒蛇的菜鸟,从今年夏天开始自学。我正在阅读scrapy教程,偶尔阅读更多有关html / xml的内容,以帮助我理解scrapy。我自己的项目是模仿scrapy教程,以便抓住http://www.gamefaqs.com/boards/916373-pc。我想获得一个主题标题列表以及主题网址,应该很简单!

我的问题在于不理解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,那么我将在此路径中添加什么? 我想程序返回的结果是这样的 线程名称 线程网址 我知道代码不是很正确,但有人可以帮我改写这个以获得结果,这将有助于我更好地理解抓取过程。

1 个答案:

答案 0 :(得分:2)

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

对于gamefaqs,文章链接如下:

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将是一个填写网址模板的字符串,但如果您需要计算以前的ID等,请将其转换为数字:

idInt = int(idStr)

我希望这会有所帮助。