用Scrapy爬取所有上市公司的股票代码和名称

来源:互联网 发布:王者霸域 纯净数据库 编辑:程序博客网 时间:2024/06/11 02:25

貌似只有凤凰财经提供了一个股票列表,
沪市的是http://app.finance.ifeng.com/list/stock.php?t=ha&f=symbol&o=asc&p=1
深市的是http://app.finance.ifeng.com/list/stock.php?t=sa&f=symbol&o=asc&p=1

曾经爬这个的时候,用的urllib2 + BeautifulSoup的办法,后来知道了Scrapy,学习了一下发现,以前的办法太low了。

以前的办法就不说了,下面记录一下用Scrapy的方法。

# -*- coding: utf-8 -*-from scrapy.spider import BaseSpiderfrom Stock.items import NameItemfrom scrapy.selector import Selectorfrom scrapy.http import Requestclass StockNameSpider(BaseSpider):    name = "stock_name"    #allowed_domains = ["http://app.finance.ifeng.com"]    start_urls = ["http://app.finance.ifeng.com/list/stock.php?t=ha&f=symbol&o=asc&p=1",                  "http://app.finance.ifeng.com/list/stock.php?t=sa&f=symbol&o=asc&p=1"    ]    def parse(self, response):        sel = Selector(response)        links = sel.xpath('//*[@class= "tab01"]/table/tr[position()>1]')        for link in links:            code = link.xpath('td[1]/a/text()').extract()            name = link.xpath('td[2]/a/text()').extract()            nameitem = NameItem()            nameitem['code'] = code            nameitem['name'] = name            yield nameitem        for url in sel.xpath('//*[@class= "tab01"]/table/tr[52]/td/a/@href').extract():            url = "http://app.finance.ifeng.com/list/stock.php" + url            yield Request(url, callback = self.parse)

注意的问题

  1. allowed_domains = ["http://app.finance.ifeng.com"]这一句在这个网站不能用。allowed_domains =是为OffsiteMiddleware服务的,目的是过滤出所有URL不由该spider负责的Request。

    当spide返回一个主机名不属于该spider的request时, 该中间件将会做一个类似于下面的记录:
    DEBUG: Filtered offsite request to 'www.othersite.com': <GET http://www.othersite.com/some/page.html>
    如果spider没有定义allowed_domains 属性,或该属性为空, 则offsite 中间件将会允许所有request。

  2. 在FIreBug里看到的HTML结构跟直接右键看源代码的结构未必一致。
    例如:

    <div class="tab01"> <table width="914" border="0" cellspacing="0" cellpadding="0">  <tr>    <th><a href="?t=ha&f=symbol&o=desc&p=1">代码&uarr;</a></th>    <th><a href="?t=ha&f=name&o=desc&p=1">名称</a></th>    <th><a href="?t=ha&f=last&o=desc&p=1">最新价</a></th>    <th><a href="?t=ha&f=chg_pct&o=desc&p=1">涨跌幅</a></th>    <th><a href="?t=ha&f=chg&o=desc&p=1">涨跌额</a></th>    <th><a href="?t=ha&f=volume&o=desc&p=1">成交量</a></th>    <th><a href="?t=ha&f=amount&o=desc&p=1">成交额</a></th>    <th><a href="?t=ha&f=open&o=desc&p=1">今开盘</a></th>    <th><a href="?t=ha&f=hst_close&o=desc&p=1">昨收盘</a></th>    <th><a href="?t=ha&f=low&o=desc&p=1">最低价</a></th>    <th><a href="?t=ha&f=high&o=desc&p=1">最高价</a></th>  </tr>  <tr>    <td><a href="http://finance.ifeng.com/app/hq/stock/sh600071/index.shtml" target="_blank">600071</a></td>    <td><a href="http://finance.ifeng.com/app/hq/stock/sh600071/index.shtml" target="_blank">凤凰光学</a></td>    <td><span class="Agreen">17.060</span></td>    <td><span class="Agreen">-0.987%</span></td>    <td><span class="Agreen">-0.17</span></td>    <td>41446手</td>    <td>7064万</td>    <td><span class="Agreen">17.15</span></td>    <td>17.23</td>    <td><span class="Agreen">16.81</span></td>    <td><span class="Ared">17.25</span></td>  </tr>

    但在FireBug看到的却不是这样。若根据FireBug的,则股票代码的Xpath该这么写//*[@class= "tab01"]/table/tbody/tr[*]/td[1]/a/text()但这样是错的。
    根据源代码正确的结果应是//*[@class= "tab01"]/table/tr[*]/td[1]/a/text()。为了避免这种情况发生,一定要在Scrapy的Shell里试写Xpath,代码是:

    scrapy shell urlresponse.xpath(' ')
  3. nameitem['code'] = code这里写作nameitem['code'] = code[0]的话会报IndexError: list index out of range的错误,虽然我也不知道为什么

  4. 如何爬取起始网页下一页的信息?
    实现原理是获取网页下一页的url,然后继续请求。因此,用Xpath抓取url的链接,放到Request()中去。
    例如
    python
    for url in sel.xpath('//*[@class= "tab01"]/table/tr[52]/td/a/@href').extract():
    url = "http://app.finance.ifeng.com/list/stock.php" + url
    yield Request(url, callback = self.parse)

    由HTML发现,下一页的链接是如?t=ha&f=symbol&o=asc&p=1样式的,因此下一页的网址需要拼接。
    我无法理解的地方在于,这里一定要使用url = * + url的方式,否则网址拼合不上。

本人非计算机专业出身,学习Python也很业余,全凭想用Python解决实际问题的兴趣而坚持,若有大牛发现文中问题,请不吝赐教

0 0
原创粉丝点击