【问题标题】:Scrapy Python spider unable to find links using LinkExtractor or by manual Request()Scrapy Python 蜘蛛无法使用 LinkExtractor 或手动 Request() 找到链接
【发布时间】:2014-09-02 20:27:32
【问题描述】:

我正在尝试编写一个爬取域上所有结果页面的 Scrapy 蜘蛛:https://www.ghcjobs.apply2jobs.com...。代码应该做三件事:

(1) 浏览 1-1000 的所有页面。这些页面是相同的,除了 URL 的最后部分不同:&CurrentPage=#。

(2) 访问包含职位发布的结果表中的每个链接,其中链接的 class= SearchResult。这些是表中唯一的链接,所以我在这里没有任何问题。

(3) 将职位描述页面上显示的信息以 key:value JSON 格式存储。 (这部分工作,以基本的方式)

我以前使用过scrapy和CrawlSpiders,使用'rule = [Rule(LinkExtractor(allow='方法递归解析页面以查找与给定正则表达式模式匹配的所有链接。我目前在第1步上感到困惑,爬过上千个结果页面。

下面是我的蜘蛛代码:

from scrapy.contrib.spiders import CrawlSpider, Rule
from scrapy.http.request import Request
from scrapy.contrib.linkextractors import LinkExtractor
from genesisSpider.items import GenesisJob

class genesis_crawl_spider(CrawlSpider):
    name = "genesis"
    #allowed_domains = ['http://www.ghcjobs.apply2jobs.com']
    start_urls = ['https://www.ghcjobs.apply2jobs.com/ProfExt/index.cfm?fuseaction=mExternal.returnToResults&CurrentPage=1']

    #allow &CurrentPage= up to 1000, currently ~ 512
    rules = [Rule(LinkExtractor(allow=("^https://www.ghcjobs.apply2jobs.com/ProfExt/
index.cfm\?fuseaction=mExternal.returnToResults&CurrentPage=[1-1000]$")), 'parse_inner_page')]

def parse_inner_page(self, response):
    self.log('===========Entrered Inner Page============')
    self.log(response.url)
    item = GenesisJob()
    item['url'] = response.url

    yield item

这是蜘蛛的输出,顶部有一些执行代码被截断:

2014-09-02 16:02:48-0400 [genesis] DEBUG: Crawled (200) <GET https://www.ghcjobs
.apply2jobs.com/ProfExt/index.cfm?fuseaction=mExternal.returnToResults&CurrentPa
ge=1> (referer: None) ['partial']
2014-09-02 16:02:48-0400 [genesis] DEBUG: Crawled (200) <GET https://www.ghcjobs
.apply2jobs.com/ProfExt/index.cfm?CurrentPage=1&fuseaction=mExternal.returnToRes
ults> (referer: https://www.ghcjobs.apply2jobs.com/ProfExt/index.cfm?fuseaction=
mExternal.returnToResults&CurrentPage=1) ['partial']
2014-09-02 16:02:48-0400 [genesis] DEBUG: ===========Entrered Inner Page========
====
2014-09-02 16:02:48-0400 [genesis] DEBUG: https://www.ghcjobs.apply2jobs.com/Pro
fExt/index.cfm?CurrentPage=1&fuseaction=mExternal.returnToResults
2014-09-02 16:02:48-0400 [genesis] DEBUG: Scraped from <200 https://www.ghcjobs.
apply2jobs.com/ProfExt/index.cfm?CurrentPage=1&fuseaction=mExternal.returnToResu
lts>
        {'url': 'https://www.ghcjobs.apply2jobs.com/ProfExt/index.cfm?CurrentPag
e=1&fuseaction=mExternal.returnToResults'}
2014-09-02 16:02:48-0400 [genesis] INFO: Closing spider (finished)
2014-09-02 16:02:48-0400 [genesis] INFO: Dumping Scrapy stats:
        {'downloader/request_bytes': 930,
         'downloader/request_count': 2,
         'downloader/request_method_count/GET': 2,
         'downloader/response_bytes': 92680,
         'downloader/response_count': 2,
         'downloader/response_status_count/200': 2,
         'finish_reason': 'finished',
         'finish_time': datetime.datetime(2014, 9, 2, 20, 2, 48, 611000),
         'item_scraped_count': 1,
         'log_count/DEBUG': 7,
         'log_count/INFO': 7,
         'request_depth_max': 1,
         'response_received_count': 2,
         'scheduler/dequeued': 2,
         'scheduler/dequeued/memory': 2,
         'scheduler/enqueued': 2,
         'scheduler/enqueued/memory': 2,
         'start_time': datetime.datetime(2014, 9, 2, 20, 2, 48, 67000)}
2014-09-02 16:02:48-0400 [genesis] INFO: Spider closed (finished)

目前,我坚持这个项目的目标 (1)。如您所见,我的蜘蛛只爬过 start_url 页面。我的正则表达式应该正确定位页面导航按钮,因为我已经测试了正则表达式。我的回调函数 parse_inner_page 正在工作,正如我插入的调试注释所示,但仅在第一页上。我是否错误地使用了“规则”?我在想也许是 HTTPS 的页面应该归咎于......

作为修补解决方案的一种方式,我尝试对第二页结果使用手动请求;这没有用。这也是它的代码。

Request("https://www.ghcjobs.apply2jobs.com/ProfExt/index.cfm?fuseaction=mExternal.returnToResults&CurrentPage=2",  callback = 'parse_inner_page')

任何人都可以提供任何指导吗?有没有更好的方法来做到这一点?自周五以来,我一直在研究 SO / Scrapy 文档。非常感谢。

更新:我已经解决了这个问题。问题出在我使用的起始网址上。

start_urls = ['https://www.ghcjobs.apply2jobs.com/ProfExt/index.cfm?fuseaction=mExternal.returnToResults&CurrentPage=1'] 

通过点击This 页面上的“搜索”按钮,进入表单提交后页面。这会在客户端运行 javascript 以向服务器提交表单,服务器会报告完整的工作板,第 1-512 页。但是,存在另一个硬编码的 URL,它显然调用服务器而不需要使用任何客户端 javascript。所以现在我的起始网址是

start_urls = ['https://www.ghcjobs.apply2jobs.com/ProfExt/index.cfm?fuseaction=mExternal.searchJobs']

一切都回到了正轨!以后看看有没有javascript独立的url来调用服务器资源。

【问题讨论】:

标签: python regex scrapy web-crawler


【解决方案1】:

您确定 Scrapy 以与您相同的方式查看网页吗?如今,越来越多的网站是由 Javascript、Ajax 构建的。这些动态内容可能需要一个功能齐全的浏览器才能完全填充。然而,Nutch 和 Scrapy 都不会处理那些开箱即用的问题。

首先,你需要确保你感兴趣的网页内容可以被scrapy检索到。有几种方法可以做到这一点。我通常使用urllib2beautifulsoup4 快速尝试一下。你的起始页没有通过我的测试。

$ python
Python 2.7.6 (default, Mar 22 2014, 22:59:56) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import urllib2
>>> from bs4 import BeautifulSoup
>>> url = "https://www.ghcjobs.apply2jobs.com/ProfExt/index.cfm?fuseaction=mExternal.returnToResults&CurrentPage=1"

>>> html = urllib2.urlopen(url).read()
>>> soup = BeautifulSoup(html)
>>> table = soup.find('div', {'id':'VESearchResults'})
>>> table.text
u'\n\n\n\r\n\t\t\tJob Title\xa0\r\n\t\t\t\r\n\t\t\n\r\n\t\t\tArea of Interest\xa0\r\n\t\t\t\r\n\t\t\n\r\n\t\t\tLocation\xa0\r\n\t\t\t\r\n\t\t\n\r\n\t\t\tState\xa0\r\n\t\t\t\r\n\t\t\n\r\n\t\t\tCity\xa0\r\n\t\t\t\r\n\t\t\n\n\n\r\n\t\t\t\t\tNo results matching your criteria.\r\n\t\t\t\t\n\n\n'
>>> 

如您所见,“没有符合您条件的结果!” 我认为您可能需要弄清楚为什么没有填充内容。饼干?发布而不是获取?用户代理..等

另外,您可以使用 scrapy parse 命令来帮助您调试。例如,我经常使用这个命令。

scrapy parse http://example.com --rules

其他一些scrapy commands,也许Selenium 可能会有所帮助。

在这里,我在 iPython 中使用运行 scrapy shell 来检查您的启动 url,并且我在浏览器中看到的第一条记录包含 Englewood,并且它不存在于 scrapy 抓取的 html 中

更新:

你正在做的是一个非常微不足道的抓取工作,你真的不需要 Scrapy,这有点矫枉过正。以下是我的建议:

  1. 看看Selenium(我假设你写的是Python),当你尝试在服务器上运行它时,最后制作无头Selenium。
  2. 您可以使用 PhantomJS 来实现这一点,它是一个更轻量级的 Javascript 执行器来完成您的工作。 Here 是另一个可能有用的 stackoverflow 问题。
  3. 几个other 资源,您可以在其中谋生。

【讨论】:

  • 汤里没有出现“Englewood”,这很奇怪。我在页面源代码中的 HTML 表格@代码行 839 中找到了它。关于您对 Ajax 调用的怀疑;我和同事一起查看了 google chrome 的页面控制台,没有看到任何 Ajax 调用... 是什么导致 HTML 对 scrapy/beautifulsoup 不可见?
  • @deusofnull 这是一个问题,也是应该努力的地方。你不能只检查浏览器中的元素并假设你看到的任何东西都应该出现在 Scrapy 中。也许清除您的缓存、cookie 并禁用 Javascript,然后我假设您在浏览器中看到的任何内容都应该与 Scrapy 看到的相似。看了一眼,好像没那么容易。
  • 天哪,这解释了很多。我查看了没有启用 JS 的页面,毫不奇怪,表格是空的……我在 github 上找到了一个名为 scrappyjs 的 scrapy 插件。希望它可以帮助?否则,您是否熟悉我可以采取的任何途径来为 scrapy 提供 javascript 功能?
  • @deusofnull 查看更新,希望对您有所帮助。有时您可以仔细监控网络选项卡,查看哪个 ajax 调用填充内容并避免使用 Selenium 或 PhantomJS ......但在最坏的情况下。硒总是有效的。
  • 这很有帮助,谢谢!实际上,我刚刚发现填充的搜索表似乎是一个硬编码的 URL,它现在正确地遵守了我的规则!随着我进一步了解它,将用这些新信息更新我的问题!我的公司实际上将 casper/phantom js 用于蜘蛛,但在某些情况下,性能确实很差。这就是一个例子,也是我设计 python 蜘蛛的原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多