Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何使用scrapy进入FanFraction.net的下一章?_Python_Web Scraping_Scrapy - Fatal编程技术网

Python 如何使用scrapy进入FanFraction.net的下一章?

Python 如何使用scrapy进入FanFraction.net的下一章?,python,web-scraping,scrapy,Python,Web Scraping,Scrapy,在FanFraction.net上,这是获取故事章节的HTML代码: 1.第一章 2.营地 3.第三章 我想用它继续下载下一章的文本内容,但通常的做法是递归调用self.fanfiriby(),因为self.storyNum+=1行,这不起作用 导入碎片、docx、时间 将子进程作为sp导入 类下载器(scrapy.Spider): name=“粉丝小说” storyNum=0 下一页=假 URL=[] docText='' 标题=“” def start_请求(自我): sp.call('

在FanFraction.net上,这是获取故事章节的HTML代码:


1.第一章
2.营地
3.第三章
我想用它继续下载下一章的文本内容,但通常的做法是递归调用
self.fanfiriby()
,因为
self.storyNum+=1
行,这不起作用

导入碎片、docx、时间
将子进程作为sp导入
类下载器(scrapy.Spider):
name=“粉丝小说”
storyNum=0
下一页=假
URL=[]
docText=''
标题=“”
def start_请求(自我):
sp.call('cls',shell=True)
self.url=list(str(输入(“输入url,用逗号和空格(,):”)分隔)。拆分(“,”)
对于self.url中的url:
如果self.url[self.storyNum].startswith('https://www.fanfiction.net/s/'):
生成scrapy.Request(url=url,callback=self.fanfiration)
elif self.url[self.storyNum].startswith('https://www.wattpad.com/'):
生成scrapy.Request(url=url,callback=self.wattpad)
其他:
打印('不是有效链接,正在结束下载程序')
时间。睡眠(5)
退出
sp.call('cls',shell=True)
def Fan虚构(自我,回应):
self.storyNum+=1
doc=docx.Document()
章节=“”
总章数=0
当前章节=1
i=0
css('div#storytext>p')中的段落:
text=(para.xpath('text()|*/text()|*/*/text()').getall())
self.title=(response.xpath('/*[@id=“profile_top”]/b/text()).get())
storyId=((response.xpath('/*[@id=“profile_top”]/span[4]/text()[5]').get()).replace('-id:','')
chapters=(response.xpath('/*[@id=“chap_select”]/option/text()).getall())
totalChapters=len(章节[0:int(len(章节)/2)])
最终文本=[
[x.replace('\u00ef','i')。replace('\u2013','-')。replace('\u2026','…')表示文本中的x],
[“故事%s:%s%”(self.storyNum,self.url[self.storyNum-1]),
[“标题:%s%”(self.Title)],
[“故事ID:%s%”(故事ID)],
[“总章节数:%s%”(总章节数)],
['章节名称:%s%[章节[0:int(len(章节)/2)]],
]
如果len(finalText[0][0])>1:
self.docText=(''.join(finalText[0][0:]))
其他:
self.docText=finalText[0][0]
如果self.nextPage==False:
文件添加段落(self.docText)
其他:
文档添加\页面\中断(self.docText)
self.nextPage=False
添加文件第()段
sp.call('cls',shell=True)
doc.save(“./../%s.docx%”(self.title))
i+=1
收益率{'line'+str(i):finalText}
sp.call('cls',shell=True)
def wattpad(自身,响应):
通过

您真的需要为故事编号保留计数器吗

我认为只要找到下一页,你就可以进入下一页,比如:

if response.xpath('//button[text()="Next >"]'):
    next_link = response.xpath('//button[text()="Next >"]')[0].attrib['onclick'].replace('self.location=', '').replace("'", '')
    yield response.follow('https://www.fanfiction.net' + next_link, self.fanfiction)
正如在评论中提到的,您应该使用项目管道来关心在文档中“存储”您的项目

这里有一些东西给你一个想法,这对我来说很有用,你必须适应你的用例:

import docx
import scrapy

class StoryPipeline:

    def open_spider(self, spider):
        self.doc = docx.Document()

    def process_item(self, item, spider):
        if 'title' in item:
            self.title = item['title']
            self.doc.add_paragraph(str(item))
        else:
            self.doc.add_paragraph('\n\n'.join(item['paragraphs']))

    def close_spider(self, spider):
        self.doc.save('./%s.docx' % (self.title))


class FanfictionDownloader(scrapy.Spider):

    name = "fanfiction.net"

    custom_settings = {
        "ITEM_PIPELINES": {
            "myspider.StoryPipeline": 300,
        }
    }

    def start_requests(self):
        start_url = 'https://www.fanfiction.net/s/11734723/1/This-Past-Storm'
        yield scrapy.Request(url=start_url, callback=self.parse)

    def parse(self, response):

        title = response.xpath('//*[@id="profile_top"]/b/text()').get()
        storyId = response.xpath('//*[@id="profile_top"]/span[4]/text()[5]').get().replace(' - id: ', '')
        chapters = response.xpath('(//select[@id="chap_select"])[1]/option/text()').getall()

        yield {
            'title': title,
            'storyId': storyId,
            'chapters': chapters,
            'totalChapters': len(chapters),
        }

        for x in self._parse_paragraphs(response):
            yield x

    def parse_next(self, response):

        for x in self._parse_paragraphs(response):
            yield x

    def _parse_paragraphs(self, response):
        paragraphs = response.xpath('//div[@id="storytext"]//text()').getall()

        yield {'paragraphs': paragraphs}

        next_button = response.xpath('(//button[text()="Next >"])[1]/@onclick').get()
        if next_button:
            next_url = next_button.replace('self.location=', '').replace("'", '')
            yield scrapy.Request(url=response.urljoin(next_url), callback=self.parse_next)

如果我这样做,文件将被覆盖。是的,因为您在爬行器中混合了关注点。您的爬行器应该关注导航和从页面获取项目。理想情况下,文档中项目的持久性应该在项目管道中完成:-在项目管道中,您可以在open_spider()中打开文档,使用process_item()添加元素,并在close_spider()中关闭文档。您可以发布一个示例,或者如何完成?我是个新手