您当前的位置: 首页 >  scrapy

暂无认证

  • 14浏览

    0关注

    93978博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

10.爬虫:超简单的scrapy(中)

发布时间:2022-09-14 16:24:34 ,浏览量:14

接上一小节:scrapy入门

六.调试代码

针对提取详细数据的代码,如果每次都debug调试,看是否能够正确的提取出来,则会发过多的请求.

scrapy提供一种方法,可以直接调试

alt

当程序运行到此处时会阻塞,这时你可以尽情的调试。当调试完成后按Ctrl-D(Windows下Ctrl-Z)退出后继续运行,当下一次运行此处时又会阻塞在这里供你调试

alt

另外,在cmd命令行输入scrapy shell 网址也可以实现相同的调试目的,将可以正确提取数据的代码拷贝到程序中

如果要在程序中debug,则不需要yield太多的url给scrapy,只需一个url即可 alt

补充一个小知识点: #针对动态网页,评论数点赞数等需要分析出url重新请求,来获取数据 html = requests.get(parse.urljoin(response.url, "/NewsAjax/GetAjaxNewsInfo?contentId={}".format(post_id))) #1.这是一个同步的代码,会等待结果返回后在往下执行,优点在于好理解,但一般不用在异步框架scrapy中 #2./NewsAjax...这里前面加/号,则会拼接在主域名下面,如果没有加/号,则拼接在该url下面 
def parse_detail(self, response):     match_re = re.match(".*?(\d+)", response.url) #提取url最后面的id     if match_re: #有id值才是真正的文章,不是中间插入的广告         post_id = match_re.group(1) #文章id         title = response.css("#news_title a::text").extract_first("") #标题         create_data = response.css("#news_info .time::text").extract_first("")
        match_re = re.match(".*?(\d+.*)", create_data)
        if match_re:
            create_date = match_re.group(1) #发布日期         content = response.css("#news_content").extract()[0] #文章内容         tag_list = response.css(".news_tags a::text").extract()
        tags = ",".join(tag_list) #标签         #同步请求代码,在并发要求不是很高时可以采用         html = requests.get(parse.urljoin(response.url, "/NewsAjax/GetAjaxNewsInfo?contentId={}".format(post_id)))
        j_data = json.loads(html.text)
        praise_nums = j_data["DiggCount"] # 点赞数         fav_nums = j_data["TotalView"] # 查看数         comment_nums = j_data["CommentCount"] # 评论数     
七.items组件

items可以解决字段过多时的,用于承载数据,在各个方法/组件中统一传递数据的问题;

class CnblogsArticleItem(scrapy.Item):     title = scrapy.Field()  # 标题     create_date = scrapy.Field()  # 发布日期     url = scrapy.Field()
    url_object_id = scrapy.Field()  # url的MD5生成,把url限定在一定的长度内,作为数据库主键     front_image_url = scrapy.Field()  # 图片url(scrapy可自动下载)     front_image_path = scrapy.Field()  # 图片下载在电脑上的路径     praise_nums = scrapy.Field()  # 点赞数     comment_nums = scrapy.Field()  # 评论数     fav_nums = scrapy.Field()  # 查看数     tags = scrapy.Field()  # 标签     content = scrapy.Field()  # 文章内容 
from ArticleSpider.items import CnblogsArticleItem
... def parse_detail(self, response):     article_item = CnblogsArticleItem()
    ...
    article_item["title"] = title
    article_item["create_date"] = create_date
    article_item["content"] = content
    article_item["tags"] = tags
    article_item["url"] = response.url
    # 重要:通过scrapy自动下载图片,这个存储图片url的值一定要是一个列表,如果列表有多个值,scrapy就会循环把图片全部下载下来     article_item["front_image_url"] = [response.meta.get("front_image_url", "")] 
    # 通过article_item传递数据     yield Request(url=parse.urljoin(response.url, "/NewsAjax/GetAjaxNewsInfo?contentId={}".format(post_id)),
                          meta={"article_item": article_item}, callback=self.parse_nums)
           
            # 处理动态网页的数据提取,将article_item传递进来并填充数据            def parse_nums(self, response):     j_data = json.loads(response.text)
    # 通过article_item取出数据     article_item = response.meta.get("article_item", "")
    praise_nums = j_data["DiggCount"]
    fav_nums = j_data["TotalView"]
    comment_nums = j_data["CommentCount"]
    
    article_item["praise_nums"] = praise_nums
    article_item["fav_nums"] = fav_nums
    article_item["comment_nums"] = comment_nums
    article_item["url_object_id"] = common.get_md5(article_item["url"])  # url的MD5生成,把url限定在一定的长度内,作为数据库主键     #已经将所有的值全部提取出来,存放于item中      yield article_item 

scrapy任何地方都可以yield一个Request与item

yield Request可以交给scrapy去下载url

yield item可以交给pipelines做持久化操作

八.pipelines 管道

打开项目目录下settings.py文件

ITEM_PIPELINES = {
   'ArticleSpider.pipelines.ArticlespiderPipeline': 300,
}

这是系统默认的配置,代表一个个"管道",路径是写在项目目录下pipelines.py中的类

class ArticlespiderPipeline(object):     def process_item(self, item, spider):         return item

每一个被yield出来的item,会依次进入这些管道类,执行process_item()方法,方法的参数item是scrapy注入进来的.

方法执行完毕后return item,item会进入下一个管道(顺序跟配置的数值有关),如果不return item,则不会在进来之后的pipelines.

一般在pipeline中做保存数据的处理;

以上,主要介绍了数据的提取,及携带数据的item的传递,传递到pipeline

九.如何让scrapy帮我们自动下载文件/图片 alt

首先在settings.py中加上内置的pipeline,

然后配置上存储的路径,

还需要指出存储图片url的字段(人家才知道去哪里下载)

alt alt
ITEM_PIPELINES = {
   'scrapy.pipelines.images.ImagesPipeline': 1,  # 1.内置的pipeline }

IMAGES_URLS_FIELD = "front_image_url"  # 3.指出存储图片url的字段(人家才知道去哪里下载) project_dir = os.path.abspath(os.path.dirname(__file__))
IMAGES_STORE = os.path.join(project_dir, 'images') # 2.配置上存储的路径 

注意点:

1.python环境中需要事先安装pillow

2.通过scrapy自动下载图片,这个存储图片url的字段值一定要是一个列表,如果列表有多个值,scrapy就会循环把图片全部下载下来

article_item["front_image_url"] = [response.meta.get("front_image_url", "")]

这样配置之后,默认的pipeline就会下载图片,并保存到对应的路径当中

3.如果我们需要存储文件的下载路径,则需要继承内置的pipeline,重写某个方法

#pipelines.py class ArticleImagePipeline(ImagesPipeline):     def item_completed(self, results, item, info):         if "front_image_url" in item:
            for ok, value in results:
                image_file_path = value["path"] ###             item["front_image_path"] = image_file_path
        return item
         #settings.py ITEM_PIPELINES = {
    # ArticleImagePipeline继承了内置的pipeline:ImagesPipeline    'ArticleSpider.pipelines.ArticleImagePipeline': 1,  
}

本文由 mdnice 多平台发布

关注
打赏
1655516835
查看更多评论
立即登录/注册

微信扫码登录

0.0478s