本系統的這部分内容好像沒什麼好寫的,就不從Scrapy基礎開始說了,挑一些重點部分和容易出錯的地方
來寫一下。其中前程無憂和智聯招聘用的是scrapy,拉勾網因為反爬太強了,用的是selenium,隻能降低采集效率,用的是用selenium模拟登入,并且還得手動輸入驗證碼(九宮格的驗證碼難以識别,找了好幾個平台聯系客服都說無法識别這種,就沒怎麼繼續找了,雖然手動比較low)
1,對與用Scrapy爬取前程無憂和智聯招聘的具體的過程就省略了。我爬的是這兩個招聘網站中的IT崗位資訊,前期沒有設計好,導緻爬蟲數量很多,想要很好的入庫就得用異步插入的方式,因為scrapy是Twisted異步架構,如果使用傳統的pymysql,commit插入方式就很有可能導緻入庫不完整的情況,因為scrapy的采集速度要遠遠大于同步插入的速度,是以,也應該使用異步插入的方式來儲存資料,具體方法如下:
導入twisted:
import MySQLdb
from twisted.enterprise import adbapi
import MySQLdb.cursors
定義MysqlTwistedPipline類:
class MysqlTwistedPipline(object):
def __init__(self, dbpool):
self.dbpool = dbpool
@classmethod
def from_settings(cls, settings):
dbparms = dict(
host=settings["MYSQL_HOST"],
db=settings["MYSQL_DBNAME"],
user=settings["MYSQL_USER"],
passwd=settings["MYSQL_PASSWORD"],
charset='utf8',
cursorclass=MySQLdb.cursors.DictCursor,
use_unicode=True,
)
dbpool = adbapi.ConnectionPool("MySQLdb", **dbparms)
return cls(dbpool)
根據不同爬蟲名字來執行不同的插入語句:
def process_item(self, item, spider):
# 使用twisted将mysql插入變成異步執行
if spider.name == 'qc_java' or spider.name == 'zl_java':
query = self.dbpool.runInteraction(self.do_insert_java, item)
query.addErrback(self.handle_error, item, spider) # 處理異常
elif spider.name == 'qc_python' or spider.name == 'zl_python':
query = self.dbpool.runInteraction(self.do_insert_python, item)
query.addErrback(self.handle_error, item, spider)
elif spider.name == 'qc_golang' or spider.name == 'zl_golang':
query = self.dbpool.runInteraction(self.do_insert_golang, item)
query.addErrback(self.handle_error, item, spider)
elif spider.name == 'qc_cplus' or spider.name == 'zl_cplus':
query = self.dbpool.runInteraction(self.do_insert_cplus, item)
query.addErrback(self.handle_error, item, spider)
elif spider.name == 'qc_bigdata' or spider.name == 'zl_bigdata':
query = self.dbpool.runInteraction(self.do_insert_bigdata, item)
query.addErrback(self.handle_error, item, spider)
elif spider.name == 'qc_arithmetic' or spider.name == 'zl_arithmetic':
query = self.dbpool.runInteraction(self.do_insert_arithmetic, item)
query.addErrback(self.handle_error, item, spider)
elif spider.name == 'qc_ai' or spider.name == 'zl_ai':
query = self.dbpool.runInteraction(self.do_insert_ai, item)
def handle_error(self, failure, item, spider):
print(failure)
具體mysql插入語句:
def do_insert_java(self, cursor, item):
insert_sql = "insert into `zp_java` (where_from,url,url_obj_id,job_name,company_name,salary_min,salary_max,job_city,experience_year,education_need,publish_date,job_advantage_tags,position_info,job_classification,crawl_time) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"
item['url_obj_id'] = item['url_obj_id'] + "{0}".format(random.randint(61, 70))
cursor.execute(insert_sql,
(item["where_from"], item["url"], item["url_obj_id"], item["job_name"], item["company_name"], item["salary_min"], item["salary_max"],
item["job_city"], item["experience_year"], item["education_need"], item["publish_date"],
item["job_advantage_tags"], item["position_info"], item["job_classification"],
item["crawl_time"]))
2,使用Selenium模拟登陸拉鈎代碼:
try:
self.driver.get(self.login_url)
self.driver.find_element_by_css_selector("div:nth-child(2) > form > div:nth-child(1) > input").send_keys(
self.username)
time.sleep(3)
self.driver.find_element_by_css_selector("div:nth-child(2) > form > div:nth-child(2) > input").send_keys(
self.password)
time.sleep(4)
self.driver.find_element_by_css_selector(
"div:nth-child(2) > form > div.input_item.btn_group.clearfix > input").click()
time.sleep(2)
将拉勾網采集的資料一緻遇到一個bug,就是字元串轉義的問題,因為采集的字段有崗位詳情描述,這是一個longtext,裡面夾着一些特殊符号就會才入庫的時候出現報錯,要pymysql.escape_string()就可以很好的解決,這個函數是pymysql自帶的。
效果截圖: