前言
最近才發現某個販賣二手書的查詢,跟實際上的入庫的書有出入。最新更新有,但查詢沒有。
所以只好開始抓全部所有的新書,再做篩選了。
下面是碰到問題的解決方式
正文
1.擷取json資料
當網址讀出來是一段json的話,可使用json.load抓取資料,記得 引入json
import json
result = json.loads(response.body_as_unicode())
但這個是一階的方式,
如果總共有兩層(Fig. 1)的話,則要再指定欄位
(Fig. 1)
item = items.usedBooksItem()
result = json.loads(response.body_as_unicode())
books = result["result1"]
for book in books:
item['title'] = book["titleMain"]
yield item
2.允許過濾相同的URL
在查問題的過程中,發現了這段字 filtered duplicate request然後才知道scrapy預設會過濾相同的url,所以要再request上面再加上 dont_filter = True
故整段request是這樣的
yield scrapy.Request(source_url,callback = self.parse, dont_filter = True)
不過scrapy其實也沒錯,你都抓過一次同樣網址的資料了,為什麼還要抓第二次。
後來才發現原因,我使用string.format 的方法組URL
source_url = " http://www.xxxxx?startNum={0">http://www.xxxxx?startNum={0}&endNum={1}"
source_url = source_url .format(“0”,”1”)
當字串取代掉的同時,本來的source_url也就沒了 {0} 跟{1}
才會導致抓的都是同一個網址。
3.python的三元表達式
常用C#的人應該還蠻習慣用 ? : 的方式來取代if else,因為夠簡潔(前提是邏輯判斷沒太複雜),一看就知道值
到了python就要改一下了。
True if condition else False
條件為True的話,結果放前面,else後面接False的程式
請注意,三元表達式不適合拿來寫太長太複雜的條件判斷
4.IndentationError: unindent does not match any outer indentation level
在寫items.py的時候一直跳這個錯誤出來,一般都是因為空白的關係。但我怎麼刪都沒有用,後來才發現,
我不應該用Notepad++去刪除空格,我應該用Atom去刪。
原因在於,我有針對atom去做python的開發環境(可參考之前寫的文章,ATOM初學Python 環境設定)。
5.錯誤 Forbidden by robots.txt
更改settting.py文件 ,另外可以加上瀏覽器抬頭
ROBOTSTXT_OBEY = False
USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36'
6.將資料透過pipelines存入資料庫
當你解析完網站內容後,要怎麼將資料存到資料庫?由於scrapy都幫你整理好了,所以不用你額外去呼叫。
但是~!!你必須有回傳值,告訴程式,你已經執行完成了。
像我下面的這段parse,解析完成後,使用yield item ,告訴start_request 執行完了,
你可以繼續執行下一步,如此才會啟動pipeline執行新增的動作(當然pipelines.py 需要自己寫一下)。
當然你也可以通通寫在主程式內,沒人阻止你。
def start_requests(self):
base_url = "https://xxxxxxum={0}&endNum={1}&sortType=1"
for page in range(1, 3):
startNum = (page-1)* 46 + 1
endNum = page * 46
source_url = base_url.format(str(startNum),str(endNum))
yield scrapy.Request(source_url,callback = self.parse, dont_filter = True)
#查詢關鍵字
def parse(self, response):
item = items.usedBooksItem()
result = json.loads(response.body_as_unicode())
books = result["result1"]
for book in books:
item['title'] = book["titleMain"]
yield item
另外,請注意return 與 yield 的不同。
Ref.
Scraping a JSON response with Scrapy
Scrapy:抓取返回數據格式為JSON的網站內容
Convert JSON array to Python list
python中 ? : 三元表達式的使用介紹
Python腳本運行出現語法錯誤:IndentationError: unindent does not match any outer indentation level
爬蟲出現Forbidden by robots.txt
0 意見:
張貼留言