pyinstaller+scrapy打包出现错误:OSError: could not get source code_Kin1713172499的博客-程序员秘密_"file \"inspect.py\", line 958, in findsource oser

技术标签: 爬虫  python  scrapy  

错误如下:

Traceback (most recent call last):
  File "scrapy\utils\defer.py", line 55, in mustbe_deferred
  File "scrapy\core\spidermw.py", line 60, in process_spider_input
  File "scrapy\core\scraper.py", line 152, in call_spider
  File "scrapy\utils\misc.py", line 218, in warn_on_generator_with_return_value
  File "scrapy\utils\misc.py", line 203, in is_generator_with_return_value
  File "inspect.py", line 985, in getsource
  File "inspect.py", line 967, in getsourcelines
  File "inspect.py", line 798, in findsource
OSError: could not get source code

这个问题困扰了我好几天,因为在PyCharm里跑是可以正常运行的,但是打包后就会报上面的错,翻遍了百度谷歌都没有找到解决办法,以为是scrapy框架不支持打包exe,然后最后从代码一步一步下手,发现是scrapy.Request传入回调的问题。

def start_requests(self):
   # 请求地址
   for url in self.start_urls:
   print("请求链接:" + url)
   yield scrapy.Request(url, callback=self.parse) # 这里要把callback=self.parse去掉

上面需要把callback=self.parse去掉,去掉后,打包后的exe就不会报找不到源代码了。去掉后默认会执行parse方法。

 

然后我又发现在parse方法里,请求下一个页面的函数里面,如果有yield也会引发此报错,一开始我的爬虫代码是这样。

import scrapy
from mangakakalot.items import MangakakalotItem
import cloudscraper

class ChapterSpider(scrapy.Spider):
    name = 'chapter'

    # 初始化
    def __init__(self,start_urls=None, *args, **kwargs):
        super(ChapterSpider, self).__init__(*args, **kwargs)
        self.start_urls = start_urls.split(",")

    # 开始请求链接
    def start_requests(self):
        # 声明 cloudscraper,用于绕过 CloudFlare
        self.browser = cloudscraper.create_scraper()
        # 请求地址
        for url in self.start_urls:
            print("请求链接:"+ url)
            yield scrapy.Request(url=url,self.parse)

    # 章节详情页
    def parse(self, response):
        comic_name = response.css("div.story-info-right>h1::text").get() # 漫画名称
        print("————解析章节详情页:" + comic_name)
        for each in response.css("ul.row-content-chapter>li"):
            chapter_url = each.css('a::attr(href)').get() # 章节详情页链接
            chapter_title = each.css('a::attr(title)').get() # 章节标题
            chapter_name = each.css('a::text').get() # 章节名称
            chapter_time = each.css('span.chapter-time::text').get() # 上传时间
            yield scrapy.Request(url=chapter_url,callback=self.parse_chapterDetail,
                                     cb_kwargs={
                                         'comic_name':comic_name,
                                         'chapter_name':chapter_name
                                     }
                                 )

    # 漫画阅读页
    def parse_chapterDetail(self, response, comic_name=None, chapter_name=None):
        if comic_name is None or chapter_name is None:
            print("漫画名或章节名不能为空")
            return
        print("————解析漫画阅读页:" + comic_name)
        for each in response.css("div.container-chapter-reader>img"):
            item = MangakakalotItem()
            item['image_urls'] = each.css("::attr(src)").getall() # 图片地址
            item['chapter_name'] = chapter_name
            item['comic_name'] = comic_name
            items.append(item)
            yield item

上面这段代码,在PyCharm里是可以正常跑的,但是用pyinstaller打包成exe后,就会报源代码不存在。然后我一次次尝试,发现是yield的问题,需要做如下修改。

import scrapy
from mangakakalot.items import MangakakalotItem
import cloudscraper

class ChapterSpider(scrapy.Spider):
    name = 'chapter'

    # 初始化
    def __init__(self,start_urls=None, *args, **kwargs):
        super(ChapterSpider, self).__init__(*args, **kwargs)
        self.start_urls = start_urls.split(",")

    # 开始请求链接
    def start_requests(self):
        # 声明 cloudscraper,用于绕过 CloudFlare
        self.browser = cloudscraper.create_scraper()
        # 请求地址
        for url in self.start_urls:
            print("请求链接:"+ url)
            yield scrapy.Request(url=url)

    # 章节详情页
    def parse(self, response):
        comic_name = response.css("div.story-info-right>h1::text").get() # 漫画名称
        print("————解析章节详情页:" + comic_name)
        for each in response.css("ul.row-content-chapter>li"):
            chapter_url = each.css('a::attr(href)').get() # 章节详情页链接
            chapter_title = each.css('a::attr(title)').get() # 章节标题
            chapter_name = each.css('a::text').get() # 章节名称
            chapter_time = each.css('span.chapter-time::text').get() # 上传时间
            yield scrapy.Request(url=chapter_url,callback=self.parse_chapterDetail,
                                     cb_kwargs={
                                         'comic_name':comic_name,
                                         'chapter_name':chapter_name
                                     }
                                 )

    # 漫画阅读页
    def parse_chapterDetail(self, response, comic_name=None, chapter_name=None):
        if comic_name is None or chapter_name is None:
            print("漫画名或章节名不能为空")
            return
        print("————解析漫画阅读页:" + comic_name)
        items = []
        for each in response.css("div.container-chapter-reader>img"):
            item = MangakakalotItem()
            item['image_urls'] = each.css("::attr(src)").getall() # 图片地址
            item['chapter_name'] = chapter_name
            item['comic_name'] = comic_name
            items.append(item)
            # yield item
        return items

去掉yield改成return,重新声明一个变量用来保存,循环结束后再返回给管道。这样exe就不会报错了。

一开始百度谷歌解决不了,我就加了几个scrapy的群问了一下,发现那些大佬只会叫你去百度,得不到任何帮助,还是得靠自己啊!

只要出现OSError: could not get source code这个错误的时候,就要注意你回调函数里的yield,在默认parse里用yield返回打包后运行是不会报错的,如果有更好的方法,欢迎各位大佬指正。

转载请注明出处!CDNS:Kin1713172499

 

 

 

 

 

 

 

 

以下省略。。。


最近弄了几个站,留个外链
ITM游戏资源
ITM资源

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_31288929/article/details/108845035

智能推荐

求凸包的周长-python_晓宜的博客-程序员秘密

题目描述平面直角坐标系中求一个凸包的周长 C。输入描述第一行输入一个 n​ ,代表测试数据量接下来 n 行输入 nn 个坐标 (x,y)1≤n≤5×10^4,∣x∣,∣y∣≤10^4​输出描述输出 C​, 结果保留 6位小数。输入输出样例示例 1输入44 84 125 9.37 8输出12.000000运行限制最大运行时间:3s 最大运行内存: 256M思路核心思想:凸包算法的基本思路是 旋转扫除,即设定

Tensorflow入门及项目_tensorflow项目_Kola_Abner的博客-程序员秘密

tensorflow+入门笔记︱基本张量tensor理解与tensorflow运行结构 原创 2017年01月22日 11:57:34 <ul class="article_t

前端笔试合集_One-Direction的博客-程序员秘密

var Object=new Object(3);⟶\longrightarrow⟶Number { 3 }var obj =[];⟶\longrightarrow⟶Array []var Object =new Object(3)(4);⟶\longrightarrow⟶TypeError: (new Object(…)) is not a functionvar Object =ne...

Bugzilla安装过程_Angus博客的博客-程序员秘密

Bugzilla+Mysql+iis+perl模块+ ActivePerl 安装过程  一、        需要的软件安装bugzilla需要的软件有MySQL数据库软件,activeperl软件,bugzilla安装包,IIS组件安装环境操作系统OS: Windows 平台Bugzilla:4.2或以上数据库:MYSQL: v5.5.21 For

最新版 sublime text 3 3176 绿色版 注释修改颜色 教程_sublime注释改为绿色_娟娟啦的博客-程序员秘密

转载自:https://blog.csdn.net/weixin_41786466/article/details/80445400#commentsedit快捷键 ctrl+shift+p 搜索 pcip 选择 Package Control: Install Package 窗口左下角显示Loading ... [  =  ],完成后 搜索并选择 PackageResource...

JS中splice、slice用法及区别_slice splice_小凳子腿的博客-程序员秘密

splice向数组中添加或删除元素,然后返回含有被删除元素的数组注意:这种方法会改变原始数组语法array.splice(index,howmany,item1,…,itemX)参数index:必需。整数,规定添加/删除项目的位置,使用负数可从数组结尾处规定位置。howmany:要删除的元素数量。如果设置为 0,则不会删除项目。如果未设置此参数,则删除从 index 开始到原数组结...

随便推点

csgo没显示重新连接服务器,csgo正在重新连接游戏服务器_Leezix的博客-程序员秘密

csgo正在重新连接游戏服务器 内容精选换一换如果操作请求在执行过程中出现异常导致未被处理,则会返回一条错误信息。错误信息中包括错误码和具体错误描述。表1列出了错误信息中的常见错误码。您可以通过表1中的处理建议进行下一步操作,处理相应的异常。云上网络互联解决方案来自:解决方案csgo正在重新连接游戏服务器 相关内容OBSBrowser+是一款用于访问和管理对象存储服务的图形化工具,支持通过配置内...

VLC 中文显示乱码问题_tools,liuming,cn_楼上的大叔阿的博客-程序员秘密

VLC 中文显示乱码问题VLC 对中文字体不是全部支持,只支持部分中文字体。导致就算设置带中文的字体 VLC 仍然可能显示口口口乱码。在 工具 -> 偏好设置 里面配置字体类型 以下字体被测试有效 DFKai-SB, Microsoft JhengHei, MingLiU, MingLiU-ExtB, MingLiU_HKSCS, MingLiU_HKSCS-ExtB, PMingLiU, PMi

matlab rx算法,精通MATLAB智能算法(2015代码)_syhakh的博客-程序员秘密

文件名大小更新时间Intelligent algorithm\10\s10_1\1.jpg535472014-04-26Intelligent algorithm\10\s10_1\s10_1.m87752014-04-26Intelligent algorithm\10\s10_2\1.jpg535472014-04-26Intelligent algorithm\10\s10_2\bys.m1...

linux shell编程总结_shell read dummy_ltbook的博客-程序员秘密

    本周学习了unix/linux shell编程,参考的是《LINUX与UNIX Shell 编程指南》,David Tansley著;徐焱,张春萌等译,由机械工业出版社出版的了,往内页那么一翻,都是2000年3月译的了,原书估计会更老,不过图书馆能找到合适于我这种初学者的也许就这么本了,将就着的吧。    这本书是以Bourne shell这个UNIX系统都支持的标准shell。Bou

微信小程序获取用户详细信息_微信小程序获取哪些用户信息_360linker的博客-程序员秘密

第一种使用wx.getUserInfo直接获取微信头像,昵称wx.getUserInfo({ success: function (res) { that.setData({ nickName: res.userInfo.nickName, avatarUrl: res.userInfo.avatarUrl, }) ...

java android 将 List中元素互换位置_yedajiang44的博客-程序员秘密

很多时候我要对List中的元素调换位置,这时候可以用如下代码,意思是将data中的index1与index2元素互换位置//data 为ListCollections.swap(data,index1,index2);