如何优雅的用 scrapy 去抓取连续页面?

2016-03-25 14:55:30 +08:00
 Shazoo
举个例子,某个社区的 member 的 profile 页。 url 形如:

http://abc.com/profile/show?id=1

id 大概是 1~2000

这个用 curl 都可以比较轻松的连续抓下来。但是在 scrapy 的框架里面,有点糊涂。

难道就是修改里面的 start_urls ,弄一个 url 列表吗?


优雅,给点优雅的方法哈。
5701 次点击
所在节点    Python
21 条回复
caizixian
2016-03-25 15:12:10 +08:00
for pagenum in range(1,2000):
____yield scrapy.Request("http://abc.com/profile/show?id={}".format(pagenum), callback=self.parse)
cyberdak
2016-03-25 15:16:36 +08:00
我想说优雅的毛啊

去知乎优雅去啊
Shazoo
2016-03-25 15:28:59 +08:00
@caizixian 这样好像和 curl 这种没啥太大区别。
wizardoz
2016-03-25 16:35:48 +08:00
有没人看着你的程序是如何跑的,优雅毛啊?
wizardoz
2016-03-25 16:38:06 +08:00
用一楼改的,够优雅了吧?

def scrapGentlyPlease(baseurl):
____for pagenum in range(1,2000):
________yield scrapy.Request("{}?id={}".format(baseurl,pagenum), callback=self.parse)
leavic
2016-03-25 16:39:19 +08:00
楼主你先给我解释一下什么叫优雅?直接放一个 url_list 这么简单的东西怎么就不优雅了?放个屁都要考虑音高吗?
Magic347
2016-03-25 17:07:57 +08:00
去页面里解析翻取下一页的 link ,然后递归调用 parse 方法即可:

def parse(self, response):
____# parse the page and yield items
____next_page = response.xpath("some link element for the next page")
____if next_page is not None:
________url_next_page = next_page.get_url()
________yield scrapy.Request(url_next_page, self.parse)
Magic347
2016-03-25 17:11:25 +08:00
此时 start_urls 初始化为列表页的首页 url 即可,
不必关心总页数到底有多少,该写法比较通用
knightdf
2016-03-25 17:47:34 +08:00
告诉你,直接放 start_urls 是最优雅的
sunchen
2016-03-25 18:27:49 +08:00
def start_requests():
for i in xrange(2000):
yield Request('http://abc.com/profile/show?id={}'.format(i))
ming2281
2016-03-25 19:53:47 +08:00
下一页一般是 ajax
到浏览器中看需要 post 哪些参数

如果页面有规律,那么本页有可能携带了下一页的信息,用 bs 提取出来
Andy1999
2016-03-25 20:07:26 +08:00
没 Get 到喷点的只有我一个人么,楼上的都吃炸药了么
ElegantOfKing
2016-03-25 21:11:42 +08:00
@Andy1999
明明一个 range+页数就能搞定的东西,要什么优雅
billgreen1
2016-03-25 21:24:47 +08:00
@leavic 你怎么知道 url 后面的 page number 有 2000 个? 如果只有 10 个,你是不是要 request 2000 次?

我定义的优雅的方式是不需要要自己手动去生成 page number, 最好能通过某种手段自动得到。比如你 request 一下 baseurl 的时候,要是能返回 total page number 就最好了。

我能想到的不优雅的方式是:
for page_number in xrange(1, a_large_number):
____try:
________request("{base_url}{page_number}".format(base_url=base_url, page_number=parge_number)
____except ExceptionIDontKnow:
break

就是设置一个比较大的 page number, 当访问不到的时候应该会返回一个特定的异常,然后就退出循环
leavic
2016-03-26 01:11:40 +08:00
@billgreen1 我怀疑你都没用过 scrapy , scrapy 直接检查 response.status == 404 就可以判断页面是否存在了,就算不检查, 404 错误根本不会爆 exception , scrapy 自己就会跳过去了。

不要问我怎么知道的,我今天刚从一个网站爬了 9 万张图片,地址就是我用 range 猜测出来的,在办公室耗时 1.5 个小时爬完。

至于什么检查一下 baseurl 就可以知道有多少 page number ,如果人家网站有这种 API 给你当然最好,问题是我还没见过哪个网站对爬虫这么友好的,纯粹给服务器找虐啊。

至于你这段代码,你怎么知道 ID=n 不存在滞后, ID=n+1 就不存在了呢,这么早 break 真的好?而且这个 ID 范围与连续性的问题楼主在问题里并没有提出,完全是你担心的结果,楼主自己都说了它用 curl 都可以抓下来了。


=============

至于那些整天高调的喊着 block 掉谁谁谁的人,嗯,欢迎鸵鸟星难民。
leavic
2016-03-26 01:18:53 +08:00
反正楼主看不到我就多说两句,不是大家有多讨厌优雅这两个字,而是写代码这东西到底什么算优雅什么算不优雅本身就是个没有标准的东西。不涉及到代码哲学而只是实现方法的话,更是很难摊上优雅不优雅。
楼主提出的这种简单至极的问题,就像 1+1=2 一样还去考虑什么优雅,那么首先你得先告诉我什么叫不优雅。
====================
简单点说,如果楼主是甲方,给你提出这个问题要求你优雅的解决,你 tm 不得跳起来问问他什么叫不优雅? start urls 怎么就不优雅了?
bear330
2016-03-26 01:32:37 +08:00
我覺得重點在於樓主用錯了詞, 如果他不要用優雅而用"彈性"來說明需求, 就不會有這麼多爭議
但他自己知道他要的優雅=彈性嗎? 沒有, 他只是抓一個"感覺", 所以用優雅這個曖昧的詞
他就像一般的客戶一樣, 其實壓根不知道自己想要的是什麼
yangqi
2016-03-26 01:32:57 +08:00
很简单,楼主只需要翘起小指,这样不管写什么代码都会很优雅了。
v2014
2016-03-26 06:29:12 +08:00
好好看看 Link Extractors
lebowsk1s
2016-03-29 10:40:11 +08:00
都给逼乎带坏了,整天优雅优雅,问你什么叫优雅又讲不出个所以然

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/266309

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX