一、命令行直接敲一行代码,优点:该方法很简单,懒人专用2.该方法不稳定,有时候没效果,具体原因暂时不清楚,具体介绍如下:
1.执行命令scrapy crawl bdbk -s JOBDIR=job_info/001
2.重新爬取时,一定要注意文件里是否有数据,如果有的话,千万不要以w或wb形式写入,否则原先内容会被覆盖。要以a或ab形式写入。
二、将已经爬取的url整理出来,每个url经过md5加密压缩,后置于集合中,每次爬取时,判断该集合中是否有该元素,有的话,pass掉,没的话继续爬。爬取大量数据时,经过md5加密压缩成较小的存储空间的文件,方便大规模抓取。优点:方法很稳定,效果很好,缺点:抓取数量过多时,可能会影响抓取效率,每一个待抓的url都要和集合中的元素对比,空间时间复杂度高。
from scrapy import Request,Spider
from crawler.items import BdbkItem
import logging
import hashlib
# 将已经抓取的url置于集合中
def creat_set():
with open('/home/tml-1/PycharmProjects/untitled/stored') as f:
data=f.read().lstrip('{').rstrip('}').split(', ')
url_st=set()
for i in data:
url_st.add(i.rstrip('\'').lstrip('\'').rstrip('\\n'))
return url_st
# 给每个已经抓取的url加密成16位的md5值
def creat_md5(url):
m=hashlib.md5()
m.update(url.encode('utf-8'))
return m.hexdigest()[8:-8]
class BaidubaikeSpider(Spider):
name = "BaiduBaike"
allowed_domains = ["baike.baidu.com"]
start_urls = 'https://baike.baidu.com/item/%E5%88%98%E7%82%B3%E6%A3%AE/2294673'
base_url = 'https://baike.baidu.com' # 百科中每个条目都具有的url
shared_str = '/item/' # 属于百科的链接中都具有的str
set_stored=creat_set()
def start_requests(self):
yield Request(url=self.start_urls, callback=self.parse)
def parse(self, response):
item = BdbkItem() # 实例化BDBKItem类
if response.status == 200: # 请求成功,执行以下代码
url_list = response.xpath("//a/@href") # 获取页面中所有链接
item['url'] = response.url # 获取当前百科条目的url,置于item中
item['title'] = response.xpath("//h1/text()").extract_first() # 获取当前百科条目的名称,置于item中
#item['time'] = time.ctime()
#self.count+=1
#logging.debug("这是debug日志,item数量{}".format(str(self.count)))
contents = response.xpath("//div[@class='para']") # 获取具有所有文本的所有div元素
text1 = [] # 新建一个空列表,用于存储文本
for content in contents:
text0 = content.xpath(".//text()").extract() # 获取一个div里面的内容,为列表形式
text0 = str(''.join(text0).strip()) # 合并列表为字符串,此为一个div里的文字内容
text1.append(text0) # 将该div里的文字内容(str)置于text1列表中
text1 = str(''.join(text1).strip()) # 将获取所有div列表内容的text1列表转为合并的字符串,获得一个百度条目的所有内容
item['text'] = text1 # 将该百度条目的内容置于item中
url_set = set() # 创建一个空集合
for url_single in url_list: # 遍历当前页面(百科条目)中所有的链接
url_set.add(url_single.extract()) # 将所有链接置于该集合中
valide_url = []
for url in url_set:
if self.shared_str in url: # 判断该链接是否有“/item/”字符串
valide_url.append(self.base_url + url) # True的话,置于列表中,该列表为我们所希望请求的有效url列表
for url in valide_url:
if creat_md5(url) not in self.set_stored:
self.set_stored.add(creat_md5(url))
yield Request(url=url, callback=self.parse, dont_filter=False)
else:
logging.info('已经爬取过了')
else: # 如果请求失败,输出warning日志
logging.warning("This url is not functional {}".format(response.url))
yield item