scrapy爬取http://www.cqn.com.cn/ms/node_1460.htm
1.先进入配置好的scrapy环境变量,用命令行创建scrapy项目
2.scrapy startproject 项目名,进入项目目录
3.scrapy genspider 爬虫名 所要爬取网页的根url
4.pycharm打开爬虫项目
5.更改settings.py文件中的
ROBOTSTXT_OBEY = False
6.在 爬虫名.py文件中编辑爬虫的逻辑
start_urls放入所要爬取文件的起始网页的url
定义解析response函数,函数操作的对象就是对url爬取过后的response结果
一般对response用xpath规则进行解析
xpath语法教程 http://www.w3school.com.cn/xpath/index.asp
根据chrome浏览器->更多工具(L)->开发者工具(D)进入爬取url的Elements,通过对想要的元素经行分析定位写入函数
一般爬取url中显示的列表->找到url的Elements中的ul标签下的li生成一个包含li的list对象,对list进行for循环找到li中的想要信息
一般爬取url中显示的表格->找到url的Elements中的table标签下的tr生成一个包含所有tr的list对象,对list进行for循环找到tr标签下的td,再生成一个包含所有td的list,对list在进行一次for循环就可以找到td内的具体内容。爬取table需要2层for循环嵌套。
我觉得在爬取table表格是先生成一个空列表,在最内层for循环将爬取到的内容添加到空列表中,同时记录tr列表的长度和td列表的长度,这样容易对table表格进行还原,对具体数据进行定位。
对于爬取具体标签中的文本会有爬取不完全的情况,所以也需要先生成一个p标签下所有文本的list对象,对list进行for循环遍历,将每一段文本拼接在一起后返回。
response.xpath('//标签类型[@标签的一个属性=“属性具体的名字”]') 适合定位到拥有唯一属性名字的标签
.//表示从根目录下所有节点
/表示当前节点的下一层节点
一般使用.// + 具体属性名进行定位
如果需要从当前url中跳转到url中包含的url需要用 yield response.follow(跳转的url,self.解析跳转url的函数名)
跳转的url不需要拼接成完成的url,只需要是从当前url中通过xpath语法定位到的a标签的href属性内容
一般爬虫会涉及的到爬取下一页的问题,可以将下一页的url做为一个变量,通过对这个变量进行if判断是否为空来判断是否存在下一页,如果不为空,就通过yield response.follow(跳转的url,self.解析跳转url的函数名)进行下一页的爬取。下一页如果为空爬取会报错,建议加一个异常处理。
一般爬取到的table表格内容需要生成csv文件好用来进行数据分析。
table表格中的数据都添加到了content列表中,先生成文件名,然后对csv文件进行写入。
csv文件每次要按行写入,所以每次写入数据的长度和爬取table表格中的tr,td两个列表的长度有关系。
import csv
import requests
import scrapy
from CQN.items import CqnItem
class CqnSpider(scrapy.Spider):
name = 'cqn'
allowed_domains = ['cqn.com.cn']
start_urls = ['http://www.cqn.com.cn/ms/node_1460.htm']
#def start_requests(self):
# url = ['http://www.cqn.com.cn/ms/node_1460.htm']
# yield scrapy.Request(url,callback=self.parse)
def parse(self, response):
next_list = response.xpath('.//span[@class="curr"]/following::*')[0]
news_list = response.xpath('//dd[@class="cont_l"]/ul/li')
for news in news_list:
item = CqnItem()
time = news.xpath(".//span/text()").extract_first()
headline = news.xpath(".//a/text()").extract_first()
link = news.xpath(".//a/@href")[0]
yield response.follow(link,self.parse_content)
if next_list:
try:
yield response.follow(next_list, self.parse)
except ValueError:
print("---------------------------------------------------------")
else:
print(next_list)
def parse_content(self,response):
tables = response.xpath('.//table')
tag=1
for table in tables:
content = []
trs = table.xpath('.//tr')
num = (int(len(trs)) - 1)
for tr in trs:
tds = tr.xpath('.//td')
lens = (int(len(tds)))
if lens==1:
tag=0
for td in tds:
text = ""
for p in td.xpath('.//p//text()'):
text = text + p.extract().strip()
content.append(text)
if(len(content)>10):
if tag == 1:
x = response.xpath('.//div[@class="Detail_Title"]/h1/text()').extract_first()
y = str(x).split("\r\n")
z = y[1].split(" ")
content.insert(0, z[8])
title = content[0] + '.csv'
with open(title,'w',encoding='utf-8',newline='') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(content[1:(lens+1)])
for i in range(num):
writer.writerow(content[(lens*(i+1)+1):(lens*(i+2)+1)])