您当前的位置: 首页 >  scrapy

奇巧小软件

暂无认证

  • 5浏览

    0关注

    16博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

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

奇巧小软件 发布时间:2022-09-14 16:24:34 ,浏览量:5

接上一小节: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.pyclass 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.pyITEM_PIPELINES = {    # ArticleImagePipeline继承了内置的pipeline:ImagesPipeline   'ArticleSpider.pipelines.ArticleImagePipeline': 1,  }

本文由 mdnice 多平台发布

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

微信扫码登录

0.0393s