『python学习』scrapy框架学习杂记

1、爬虫的 .py 文件名跟项目名不能够相同


2、一定要有 parse 函数


3、要写对 xpath 


4、name 是爬虫名


5、unicode 转码用 decode 函数


# 测试网站是博客园,时间为 2016-8-3


6、sites = hxs.xpath('//*[@class="post_item"]')

item["link"] = site.xpath('*/h3/a/@href').extract()

可以每次只提取一篇文章的链接

xpath表达式实例

7、

① sites = hxs.xpath('//*[@id="post_list"]')

item["link"] = site.xpath('//*[@class="titlelnk"]/@href').extract()

每次可以提取该页所有文章的链接

或者

sites = hxs.xpath('body')

item["link"] = site.xpath('//*[@class="titlelnk"]/@href').extract()


8、

print response.xpath('body/div[1]/div[1]/div[1]/div[1]/text()').extract()[0]

代码改变世界 


9、
print response.xpath('//*[@id="site_nav_top"]/text()').extract()[0]

代码改变世界


10、选取属于 xx 子元素的最后一个 xx 元素

print response.xpath('//*[@id="nav_menu"]/a[last()]/text()').extract()[0]

找找看


11、提取链接时,后面不要跟 /text()


12、或者页面的所有链接

print response.xpath('//@href').extract()

13、不知为何,在 IDE 和交互模式下,相同的代码返回的结果不同


14、爬取文章相关信息

# 抓取文章相关数据
    def parse(self, response):
        items = []
        hxs = HtmlXPathSelector(response)
        sites = hxs.xpath('//*[@class="post_item"]')


        for site in sites:
            item = CnbItem()
            item["link"] = site.xpath('*/h3/a/@href').extract()
            item["readNumber"] = re.findall(r"[0-9]+", site.xpath('*/div/span[2]/a/text()').extract()[0])
            item["title"] = [site.xpath('*/h3/a/text()').extract()[0].encode("utf-8").decode("utf-8")]
            item["recommendNumber"] = site.xpath('*/div/span/text()').extract()
            item["newsTime"] = re.findall(r"[0-9]+-[0-9]+-[0-9]+ [0-9]+:[0-9]+", site.xpath('*/div/text()').extract()[-1])
            item["author"] = site.xpath('*/div/a/text()').extract()
            item["comment"] = re.findall(r"[0-9]+", site.xpath('*/div/span[1]/a/text()').extract()[0])
            print "-"*100
            print repr(item).decode("unicode-escape") + "\n"
            items.append(item)
        print items
        return items


15、
# 抓取顶端的文章
    def parse(self, response):
        hxs = HtmlXPathSelector(response)
        sites = hxs.xpath('//*[@id="headline_block"]')
    
        for site in sites:
            item = CnbItem()
            link_list = site.xpath('ul/li/a/text()').extract()
            for link in link_list:
                print link.encode("utf-8").decode("utf-8")
                print "-"*100

16、爬取所有页面文章相关信息

# 抓取文章相关数据
    def parse(self, response):
        items = []
        validurls = []
        hxs = HtmlXPathSelector(response)
        all_page_urls = hxs.xpath('//*[@id="paging_block"]/*//a/@href').extract()
        for url in all_page_urls:
            validurls.append(url)
        items.extend([self.make_requests_from_url("http://www.cnblogs.com%s" % url).replace(callback=self.parse) \
                      for url in list(set(validurls))])


        sites = hxs.xpath('//*[@class="post_item"]')

        for site in sites:
            item = CnbItem()
            item["link"] = site.xpath('*/h3/a/@href').extract()
            item["readNumber"] = re.findall(r"[0-9]+", site.xpath('*/div/span[2]/a/text()').extract()[0])
            item["title"] = [site.xpath('*/h3/a/text()').extract()[0].encode("utf-8").decode("utf-8")]
            item["recommendNumber"] = site.xpath('*/div/span/text()').extract()
            item["newsTime"] = re.findall(r"[0-9]+-[0-9]+-[0-9]+ [0-9]+:[0-9]+", site.xpath('*/div/text()').extract()[-1])
            item["author"] = site.xpath('*/div/a/text()').extract()
            item["comment"] = re.findall(r"[0-9]+", site.xpath('*/div/span[1]/a/text()').extract()[0])
            print "-"*100
            print repr(item).decode("unicode-escape") + "\n"
            items.append(item)
        print items
        return items


17、回调函数

类A调用类B的方法b(传入相关信息),类B的方法在执行完后,会将结果写到(再回调)类A的方法a,完成动作。(其实方法a就是传说中的回调方法啦)


18、当要爬取多网页时,可以继承 CrawlSpider 类


19、使用 Rule 时,回调函数不要使用 parse ,而是使用 parse_x 之类作为回调函数


20、

#rules编写法一,官方文档方式  
    #rules = [  
    #    #提取“下一篇”的链接并**跟进**,若不使用restrict_xpaths参数限制,会将页面中所有  
    #    #符合allow链接全部抓取  
    #    Rule(SgmlLinkExtractor(allow=('/u012150179/article/details'),  
    #                          restrict_xpaths=('//li[@class="next_article"]')),  
    #         follow=True)  
    #  
    #    #提取“下一篇”链接并执行**处理**  
    #    #Rule(SgmlLinkExtractor(allow=('/u012150179/article/details')),  
    #    #     callback='parse_item',  
    #    #     follow=False),  
    #]  
  
    #rules编写法二,更推荐的方式(自己测验,使用法一时经常出现爬到中间就finish情况,并且无错误码)  
    rules = [  
        Rule(SgmlLinkExtractor(allow=('/u012150179/article/details'),  
                              restrict_xpaths=('//li[@class="next_article"]')),  
             callback='parse_item',  
             follow=True)  
    ]  


21、返回 items 时要返回字典形式,目前仍未知原因


22、在 setting 文件中不设置 DUPEFILTER_CLASS = 'scrapy.dupefilter.BaseDupeFilter' 的时候,不会重复爬取连接,但是加上后就会,目前原因未知


23、

from scrapy.spiders import Spider
from scrapy import Selector
from scrapy.selector import HtmlXPathSelector
from cnb.items import CnbItem
import scrapy
import logging
import re
from scrapy.contrib.spiders import CrawlSpider, Rule
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor as sle
from scrapy.http import Request
from scrapy.http import HtmlResponse

import re

class CnblogsSpider(CrawlSpider):
    name = "cnb"
    # 减慢爬取速度为 1s
    download_delay = 0.05
    allowed_domains = [r"cnblogs.com"]
    start_urls = ["http://www.cnblogs.com/#p1"]
    rules = [ # 定义爬取URL的规则
              Rule(sle(allow=(r"/sitehome/p"),
                       ),
                   # restrict_xpaths=('//*[@id="paging_block"]/*/a[last()]/@href')
                   # //*[@id="paging_block"]/div/a[13]

              follow=True, callback="parse_item", )
    ]

    # 设定日志输出格式
    logging.basicConfig(
                        level=logging.ERROR,
                        format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                        datefmt='%a, %d %b %Y %H:%M:%S',
                        filename=r'C:\Users\LCG22\PycharmProjects\Scrapy\cnb\cnb\spiders/cnb_spider.log',
                        filemode='w'
                        )

    # # 抓取文章相关数据, 无法自动翻页
    # def parse(self, response):
    #     sel = Selector(response)
    #     all_page_urls = list(set(sel.xpath('//*[@id="paging_block"]/*//a/@href').extract()))
    #     # all_page_urls = [r"http://www.cnblogs.com/#p%s" % url for url in range(1, 201)]
    #     for url in all_page_urls:
    #         url = "http://www.cnblogs.com%s" % url.replace("sitehome/p/", "#p")
    #         # print "-"*100
    #         # print "url: ", url
    #         # print "*"*100
    #         yield Request(url, callback=self.parse_page)

    def parse_item(self, response):
        print "-"*100
        print "url: ", response.url
        print "*"*100
        logging.info("url: %s" % response.url)
        sel = Selector(response)
        items = []
        items_dict = {}
        sites = sel.xpath('//*[@class="post_item"]')
        for site in sites:
            item = CnbItem()
            # item["link"] = site.xpath('*/h3/a/@href').extract()[0]
            # item["readNumber"] = int(re.findall(r"[0-9]+", site.xpath('*/div/span[2]/a/text()').extract()[0])[0])
            item["title"] = [site.xpath('*/h3/a/text()').extract()[0].encode("utf-8").decode("utf-8")][0]
            # item["recommendNumber"] = int(site.xpath('*/div/span/text()').extract()[0])
            item["newsTime"] = re.findall(r"[0-9]+-[0-9]+-[0-9]+ [0-9]+:[0-9]+", site.xpath('*/div/text()').extract()[-1])[0]
            # item["author"] = site.xpath('*/div/a/text()').extract()[0]
            # item["comment"] = int(re.findall(r"[0-9]+", site.xpath('*/div/span[1]/a/text()').extract()[0])[0])
            # print "-"*100
            # print repr(item).decode("unicode-escape") + "\n"
            items.append(item)
            logging.info("items: %s" % items)
            items_dict.update(item)
            logging.info("items_dict: %s" % items_dict)
        # yield items
        yield items_dict


24、

# 设定日志输出格式
    logging.basicConfig(
                        level=logging.ERROR,
                        format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                        datefmt='%a, %d %b %Y %H:%M:%S',
                        filename=r'C:\Users\LCG22\PycharmProjects\Scrapy\cnb\cnb\spiders/cnb_spider.log',
                        filemode='w'
                        )


25、

logging.ERROR("url: %s" % response.url)

这样写是不对的,会报错:'int' object is not callable

但 response.url 是字符串,目前仍不知道具体是哪里有问题。但是当 ERROR 改成 info 后则是正常的,而改成 INFO 后则又报同样的错,最后改成 error 后则是正常的


26、每次只提取一篇文章或类似的要求时,方法是每次都只定位到具体的文章的位置,而不是包含该页所有文章的块


27、如果前后两个元素之间没有其它元素,则不能加 */


28、allowed_domains = ["cnblogs.com"]  貌似只能写成这样的形式,而不能写成 http://www.cnblogs.com  的形式


29、'//*[@id="xxx"]'   貌似只能够写成 //* 的形式,不然会报错


30、使用 .decode("unicode-escape") 可以输出显示中文,但是 items 要是 unicode 或 utf 编码


31、过滤规则必须要使用 rules 作为变量,否则不会启用过滤规则


32、每次只提取某个块的第某个部分的时候,技巧是在获取该块的时候,获取该块的所有部分,然后再循环读取每个部分的具体元素


33、当遇到这种情况时:

可以使用这种方法:u'div[2]/span[1][contains(./text(), "工作年限:")]/following::text()[1]'

而如果遇到的是这种情况时:

可以使用正则来处理
也可以使用 sel.xpath('//li[@class="itemli-b"]//text()').extract()[-1]
通过将某属性下的所有文本全部匹配,然后再选取,但是选取该属性并不是随便选的哪一个都可以的

34、ITEM_PIPELINES 不要忘记后面的 S

35、

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值