Python 如何使用scrapy进入FanFraction.net的下一章?
在FanFraction.net上,这是获取故事章节的HTML代码: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('
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()中关闭文档。您可以发布一个示例,或者如何完成?我是个新手