采用scrapy來爬取愛奇藝電視劇頻道資料匯入mysql資料庫,但是一直有個別重復資料。麻煩指導下,看看什么問題
爬蟲程式
# -*- coding: utf-8 -*-
import scrapy
from iqiyi.items import IqiyiItem
from scrapy.selector import Selector
from scrapy.contrib.spiders import CrawlSpider,Rule
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
class IqiyiSpider(CrawlSpider):
name="iqiyi"
allowed_domains=["list.iqiyi.com"]
#download_delay=1
start_urls=["http://list.iqiyi.com/www/2/-------------11-1-1-iqiyi--.html"]
rules=[
#電視劇
Rule(SgmlLinkExtractor(allow=('http://list.iqiyi.com/www/2/-----------.*--4-\d+-1-iqiyi--.html')),callback="parse_item",follow=True)
]
def parse_item(self, response):
sel=Selector(response)
item=IqiyiItem()
#影片名稱
item['name']=sel.xpath('//p[@class="site-piclist_info_title"]/a/text()').extract()
#item['name']=[n.encode('utf8') for n in name]
#影片型別
item['classification']=sel.xpath('/html/body/div[4]/div/div/div[1]/div[1]/ul/li[@class="selected"]/a/text()').extract()
#albumid
item['albumid']=sel.xpath('//a/@data-qidanadd-albumid').extract()
#tvid
item['tvid']=sel.xpath('//a/@data-qidanadd-tvid').extract()
return item
pipelines
# -*- coding: utf-8 -*-
from scrapy import log
from twisted.enterprise import adbapi #匯入twisted的包
import MySQLdb
import MySQLdb.cursors
import datetime
class IqiyiPipeline(object):
def __init__(self): #初始化連接mysql的資料庫相關資訊
self.dbpool = adbapi.ConnectionPool(
dbapiName='MySQLdb',
host='127.0.0.1',
db = 'iqiyi',
user = 'root',
passwd = 'root',
cursorclass = MySQLdb.cursors.DictCursor,
charset = 'utf8',
use_unicode = False
)
# pipeline dafault function #這個函式是pipeline默認呼叫的函式
def process_item(self, item, spider):
query = self.dbpool.runInteraction(self._conditional_insert, item)
return item
# insert the data to databases #把資料插入到資料庫中
def _conditional_insert(self, tx, item):
lenname=len(item['name'])
item['classification']*=lenname
for n in range(lenname):
tx.execute("select * from tv1 where name=%s",(item['name'][n]))
result=tx.fetchone()
if result:
pass
else:
sql = "insert into tv1 (name,classification,albumid,tvid) values (%s,%s,%s,%s)"
tx.execute(sql,(item['name'][n],item['classification'][n],item['albumid'][n],item['tvid'][n]))
uj5u.com熱心網友回復:
哥們,你有答案了嗎。我爬取 電商的資料,也出現了大量的重復資料,而且明顯沒有把電商的所有資料爬下來。求解啊。uj5u.com熱心網友回復:
可能是連接mysql的模塊有問題,python torndb就有這種問題 查詢例外 它偶爾不報錯卻是正常的回傳一個空,所以我覺得你最好是在mysql里加一個唯一約束 或者改用其它連接模塊比如sqlalchemy比較重型點的uj5u.com熱心網友回復:
求解,我也碰到同樣問題了。uj5u.com熱心網友回復:
同求解,我也碰到同樣問題了。解決了嗎? 這邊一條解答,但沒看懂 https://segmentfault.com/q/1010000003070627/a-1020000005151057uj5u.com熱心網友回復:
我也碰到這個問題了,解決辦法是改用正則運算式決議,不用xpath。我也不知道是為什么,求高手解答
uj5u.com熱心網友回復:
資料庫中加了唯一約束,還是有,試試其他方法吧
uj5u.com熱心網友回復:
真是nb,加了唯一約束還能有重復資料,資料庫吊炸天了
uj5u.com熱心網友回復:
我遇到類似的問題,資料爬出來的是對的,入庫才會出現重復,問題處在
位置1:
位置2 : query = self.dbpool.runInteraction(self._Cate_insert, asynItem)
位置3
_Cate_insert()
位置4
這句話上,這句話之前列印到檔案就是對的,
之后列印的就會出錯,
有重復有丟失,但數目剛好是一樣的。
當_Cate_insert() 執行的時候,asynItem已經變了。
也就是說 執行順序是:
位置1:
位置2:
位置3:
位置4:
因此問題就出在 這句話是異步的,
asynItem ,這個物件,在出現了 共享出現了問題。
uj5u.com熱心網友回復:
解決辦法:import copy
#物件拷貝,深拷貝
asynItem = copy.deepcopy(item)
query = self.dbpool.runInteraction(self._Cate_insert,asynItem)
參考傳參的問題,艸
uj5u.com熱心網友回復:
樓上的很贊~~~~~~~uj5u.com熱心網友回復:
樓主試下把PIPELINES里面的30-37行,FOR回圈及查詢SQL去掉,修改為:tx.executemany(sql,list(zip(item['name'],item['classification'],item['albumid'],item['tvid'])))
據說使用executemany插入要快很多。
uj5u.com熱心網友回復:
其原因是由于Spider的速率比較快,而scapy操作資料庫操作比較慢,導致pipeline中的方法呼叫較慢,這樣當一個變數正在處理的時候,一個新的變數過來,之前的變數的值就會被覆寫,比如pipline的速率是1TPS,而spider的速率是5TPS,那么資料庫應該會有5條重復資料。
解決方案是對變數進行保存,在保存的變數進行操作,通過互斥確保變數不被修改
#pipeline默認呼叫
def process_item(self, item, spider):
#深拷貝
asynItem = copy.deepcopy(item)
d = self.dbpool.runInteraction(self._do_upinsert, asynItem, spider)
uj5u.com熱心網友回復:
也碰到同樣問題了,求解釋!uj5u.com熱心網友回復:
比如,1:同一時間爬了相同的鏈接,保存的時候資料庫都還沒有,這樣,插入的時候就同時插入了2條相同的記錄。2:雖然不是同一時間爬取相同的鏈接,但你代碼貌似只是excute,并沒有commit,因此 if result: pass這句沒有起到作用,因為這時候資料庫的確沒有存在。
uj5u.com熱心網友回復:
tx.execute("select * from tv1 where name=%s",(item['name'][n]))改成
tx.execute("select * from tv1 where name=%s",[item['name'][n]])
uj5u.com熱心網友回復:
在管道里面設定根據關鍵欄位去重,on duplicate key update name = (name),根據唯一name去重uj5u.com熱心網友回復:
把return item改成yield item試試呢uj5u.com熱心網友回復:
資料庫建表的時候,可以允許不重復uj5u.com熱心網友回復:
的確是參考傳遞問題,但是改為深拷貝,效率很慢,這樣異步的效果就沒了,該不如同步快轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/142335.html
