1、爬虫的 .py 文件名跟项目名不能够相同
2、一定要有 parse 函数
3、要写对 xpath
4、name 是爬虫名
5、unicode 转码用 decode 函数
# 测试网站是博客园,时间为 2016-8-3
6、sites = hxs.xpath('//*[@class="post_item"]')
item["link"] = site.xpath('*/h3/a/@href').extract()
可以每次只提取一篇文章的链接
7、
① sites = hxs.xpath('//*[@id="post_list"]')
item["link"] = site.xpath('//*[@class="titlelnk"]/@href').extract()
每次可以提取该页所有文章的链接
或者
sites = hxs.xpath('body')
item["link"] = site.xpath('//*[@class="titlelnk"]/@href').extract()
8、
print response.xpath('body/div[1]/div[1]/div[1]/div[1]/text()').extract()[0]
代码改变世界
9、
print response.xpath('//*[@id="site_nav_top"]/text()').extract()[0]
代码改变世界
print response.xpath('//*[@id="nav_menu"]/a[last()]/text()').extract()[0]
找找看
11、提取链接时,后面不要跟 /text()
12、或者页面的所有链接
print response.xpath('//@href').extract()
13、不知为何,在 IDE 和交互模式下,相同的代码返回的结果不同
14、爬取文章相关信息
# 抓取文章相关数据
def parse(self, response):
items = []
hxs = HtmlXPathSelector(response)
sites = hxs.xpath('//*[@class="post_item"]')
for site in sites:
item = CnbItem()
item["link"] = site.xpath('*/h3/a/@href').extract()
item["readNumber"] = re.findall(r"[0-9]+", site.xpath('*/div/span[2]/a/text()').extract()[0])
item["title"] = [site.xpath('*/h3/a/text()').extract()[0].encode("utf-8").decode("utf-8")]
item["recommendNumber"] = site.xpath('*/div/span/text()').extract()
item["newsTime"] = re.findall(r"[0-9]+-[0-9]+-[0-9]+ [0-9]+:[0-9]+", site.xpath('*/div/text()').extract()[-1])
item["author"] = site.xpath('*/div/a/text()').extract()
item["comment"] = re.findall(r"[0-9]+", site.xpath('*/div/span[1]/a/text()').extract()[0])
print "-"*100
print repr(item).decode("unicode-escape") + "\n"
items.append(item)
print items
return items
15、
# 抓取顶端的文章
def parse(self, response):
hxs = HtmlXPathSelector(response)
sites = hxs.xpath('//*[@id="headline_block"]')
for site in sites:
item = CnbItem()
link_list = site.xpath('ul/li/a/text()').extract()
for link in link_list:
print link.encode("utf-8").decode("utf-8")
print "-"*100
16、爬取所有页面文章相关信息
# 抓取文章相关数据
def parse(self, response):
items = []
validurls = []
hxs = HtmlXPathSelector(response)
all_page_urls = hxs.xpath('//*[@id="paging_block"]/*//a/@href').extract()
for url in all_page_urls:
validurls.append(url)
items.extend([self.make_requests_from_url("http://www.cnblogs.com%s" % url).replace(callback=self.parse) \
for url in list(set(validurls))])
sites = hxs.xpath('//*[@class="post_item"]')
for site in sites:
item = CnbItem()
item["link"] = site.xpath('*/h3/a/@href').extract()
item["readNumber"] = re.findall(r"[0-9]+", site.xpath('*/div/span[2]/a/text()').extract()[0])
item["title"] = [site.xpath('*/h3/a/text()').extract()[0].encode("utf-8").decode("utf-8")]
item["recommendNumber"] = site.xpath('*/div/span/text()').extract()
item["newsTime"] = re.findall(r"[0-9]+-[0-9]+-[0-9]+ [0-9]+:[0-9]+", site.xpath('*/div/text()').extract()[-1])
item["author"] = site.xpath('*/div/a/text()').extract()
item["comment"] = re.findall(r"[0-9]+", site.xpath('*/div/span[1]/a/text()').extract()[0])
print "-"*100
print repr(item).decode("unicode-escape") + "\n"
items.append(item)
print items
return items
17、回调函数
类A调用类B的方法b(传入相关信息),类B的方法在执行完后,会将结果写到(再回调)类A的方法a,完成动作。(其实方法a就是传说中的回调方法啦)
18、当要爬取多网页时,可以继承 CrawlSpider 类
19、使用 Rule 时,回调函数不要使用 parse ,而是使用 parse_x 之类作为回调函数
20、
#rules编写法一,官方文档方式
#rules = [
# #提取“下一篇”的链接并**跟进**,若不使用restrict_xpaths参数限制,会将页面中所有
# #符合allow链接全部抓取
# Rule(SgmlLinkExtractor(allow=('/u012150179/article/details'),
# restrict_xpaths=('//li[@class="next_article"]')),
# follow=True)
#
# #提取“下一篇”链接并执行**处理**
# #Rule(SgmlLinkExtractor(allow=('/u012150179/article/details')),
# # callback='parse_item',
# # follow=False),
#]
#rules编写法二,更推荐的方式(自己测验,使用法一时经常出现爬到中间就finish情况,并且无错误码)
rules = [
Rule(SgmlLinkExtractor(allow=('/u012150179/article/details'),
restrict_xpaths=('//li[@class="next_article"]')),
callback='parse_item',
follow=True)
]
21、返回 items 时要返回字典形式,目前仍未知原因
22、在 setting 文件中不设置 DUPEFILTER_CLASS = 'scrapy.dupefilter.BaseDupeFilter' 的时候,不会重复爬取连接,但是加上后就会,目前原因未知
23、
from scrapy.spiders import Spider
from scrapy import Selector
from scrapy.selector import HtmlXPathSelector
from cnb.items import CnbItem
import scrapy
import logging
import re
from scrapy.contrib.spiders import CrawlSpider, Rule
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor as sle
from scrapy.http import Request
from scrapy.http import HtmlResponse
import re
class CnblogsSpider(CrawlSpider):
name = "cnb"
# 减慢爬取速度为 1s
download_delay = 0.05
allowed_domains = [r"cnblogs.com"]
start_urls = ["http://www.cnblogs.com/#p1"]
rules = [ # 定义爬取URL的规则
Rule(sle(allow=(r"/sitehome/p"),
),
# restrict_xpaths=('//*[@id="paging_block"]/*/a[last()]/@href')
# //*[@id="paging_block"]/div/a[13]
follow=True, callback="parse_item", )
]
# 设定日志输出格式
logging.basicConfig(
level=logging.ERROR,
format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
datefmt='%a, %d %b %Y %H:%M:%S',
filename=r'C:\Users\LCG22\PycharmProjects\Scrapy\cnb\cnb\spiders/cnb_spider.log',
filemode='w'
)
# # 抓取文章相关数据, 无法自动翻页
# def parse(self, response):
# sel = Selector(response)
# all_page_urls = list(set(sel.xpath('//*[@id="paging_block"]/*//a/@href').extract()))
# # all_page_urls = [r"http://www.cnblogs.com/#p%s" % url for url in range(1, 201)]
# for url in all_page_urls:
# url = "http://www.cnblogs.com%s" % url.replace("sitehome/p/", "#p")
# # print "-"*100
# # print "url: ", url
# # print "*"*100
# yield Request(url, callback=self.parse_page)
def parse_item(self, response):
print "-"*100
print "url: ", response.url
print "*"*100
logging.info("url: %s" % response.url)
sel = Selector(response)
items = []
items_dict = {}
sites = sel.xpath('//*[@class="post_item"]')
for site in sites:
item = CnbItem()
# item["link"] = site.xpath('*/h3/a/@href').extract()[0]
# item["readNumber"] = int(re.findall(r"[0-9]+", site.xpath('*/div/span[2]/a/text()').extract()[0])[0])
item["title"] = [site.xpath('*/h3/a/text()').extract()[0].encode("utf-8").decode("utf-8")][0]
# item["recommendNumber"] = int(site.xpath('*/div/span/text()').extract()[0])
item["newsTime"] = re.findall(r"[0-9]+-[0-9]+-[0-9]+ [0-9]+:[0-9]+", site.xpath('*/div/text()').extract()[-1])[0]
# item["author"] = site.xpath('*/div/a/text()').extract()[0]
# item["comment"] = int(re.findall(r"[0-9]+", site.xpath('*/div/span[1]/a/text()').extract()[0])[0])
# print "-"*100
# print repr(item).decode("unicode-escape") + "\n"
items.append(item)
logging.info("items: %s" % items)
items_dict.update(item)
logging.info("items_dict: %s" % items_dict)
# yield items
yield items_dict
24、
# 设定日志输出格式
logging.basicConfig(
level=logging.ERROR,
format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
datefmt='%a, %d %b %Y %H:%M:%S',
filename=r'C:\Users\LCG22\PycharmProjects\Scrapy\cnb\cnb\spiders/cnb_spider.log',
filemode='w'
)
25、
logging.ERROR("url: %s" % response.url)
这样写是不对的,会报错:'int' object is not callable
但 response.url 是字符串,目前仍不知道具体是哪里有问题。但是当 ERROR 改成 info 后则是正常的,而改成 INFO 后则又报同样的错,最后改成 error 后则是正常的
26、每次只提取一篇文章或类似的要求时,方法是每次都只定位到具体的文章的位置,而不是包含该页所有文章的块
27、如果前后两个元素之间没有其它元素,则不能加 */
28、allowed_domains = ["cnblogs.com"] 貌似只能写成这样的形式,而不能写成 http://www.cnblogs.com 的形式
29、'//*[@id="xxx"]' 貌似只能够写成 //* 的形式,不然会报错
30、使用 .decode("unicode-escape") 可以输出显示中文,但是 items 要是 unicode 或 utf 编码
31、过滤规则必须要使用 rules 作为变量,否则不会启用过滤规则
32、每次只提取某个块的第某个部分的时候,技巧是在获取该块的时候,获取该块的所有部分,然后再循环读取每个部分的具体元素
33、当遇到这种情况时: